Log full signed remote commitment transaction hex in channel
[rust-lightning] / lightning / src / ln / channel.rs
index 0040541cbc18dcbc286c8a59040bd855fc1689be..d9c7fc5ad27b049d24dbe55882c3a21a0fc983ca 100644 (file)
@@ -45,6 +45,7 @@ use std::ops::Deref;
 #[cfg(any(test, feature = "fuzztarget"))]
 use std::sync::Mutex;
 use bitcoin::hashes::hex::ToHex;
+use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0;
 
 #[cfg(test)]
 pub struct ChannelValueStat {
@@ -520,13 +521,16 @@ impl<Signer: Sign> Channel<Signer> {
 
                let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
 
+               let mut secp_ctx = Secp256k1::new();
+               secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
+
                Ok(Channel {
                        user_id,
                        config: config.channel_options.clone(),
 
                        channel_id: keys_provider.get_secure_random_bytes(),
                        channel_state: ChannelState::OurInitSent as u32,
-                       secp_ctx: Secp256k1::new(),
+                       secp_ctx,
                        channel_value_satoshis,
 
                        latest_monitor_update_id: 0,
@@ -737,15 +741,14 @@ impl<Signer: Sign> Channel<Signer> {
                let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
                        match &msg.shutdown_scriptpubkey {
                                &OptionalField::Present(ref script) => {
-                                       // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg
-                                       if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wsh() || script.is_v0_p2wpkh() {
-                                               Some(script.clone())
                                        // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
-                                       } else if script.len() == 0 {
+                                       if script.len() == 0 {
                                                None
                                        // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. Fail the channel
-                                       } else {
+                                       } else if is_unsupported_shutdown_script(&their_features, script) {
                                                return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. script: ({})", script.to_bytes().to_hex())));
+                                       } else {
+                                               Some(script.clone())
                                        }
                                },
                                // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
@@ -755,13 +758,16 @@ impl<Signer: Sign> Channel<Signer> {
                        }
                } else { None };
 
+               let mut secp_ctx = Secp256k1::new();
+               secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
+
                let chan = Channel {
                        user_id,
                        config: local_config,
 
                        channel_id: msg.temporary_channel_id,
                        channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32),
-                       secp_ctx: Secp256k1::new(),
+                       secp_ctx,
 
                        latest_monitor_update_id: 0,
 
@@ -1439,15 +1445,14 @@ impl<Signer: Sign> Channel<Signer> {
                let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
                        match &msg.shutdown_scriptpubkey {
                                &OptionalField::Present(ref script) => {
-                                       // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg
-                                       if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wsh() || script.is_v0_p2wpkh() {
-                                               Some(script.clone())
                                        // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
-                                       } else if script.len() == 0 {
+                                       if script.len() == 0 {
                                                None
                                        // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. Fail the channel
+                                       } else if is_unsupported_shutdown_script(&their_features, script) {
+                                               return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. script: ({})", script.to_bytes().to_hex())));
                                        } else {
-                                               return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. scriptpubkey: ({})", script.to_bytes().to_hex())));
+                                               Some(script.clone())
                                        }
                                },
                                // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
@@ -1565,7 +1570,7 @@ impl<Signer: Sign> Channel<Signer> {
                let funding_redeemscript = self.get_funding_redeemscript();
                let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
                let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
-               let mut channel_monitor = ChannelMonitor::new(self.holder_signer.clone(),
+               let mut channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(),
                                                              &self.shutdown_pubkey, self.get_holder_selected_contest_delay(),
                                                              &self.destination_script, (funding_txo, funding_txo_script.clone()),
                                                              &self.channel_transaction_parameters,
@@ -1635,7 +1640,7 @@ impl<Signer: Sign> Channel<Signer> {
                let funding_txo = self.get_funding_txo().unwrap();
                let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
                let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound());
-               let mut channel_monitor = ChannelMonitor::new(self.holder_signer.clone(),
+               let mut channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(),
                                                              &self.shutdown_pubkey, self.get_holder_selected_contest_delay(),
                                                              &self.destination_script, (funding_txo, funding_txo_script),
                                                              &self.channel_transaction_parameters,
@@ -3066,7 +3071,7 @@ impl<Signer: Sign> Channel<Signer> {
                })
        }
 
-       pub fn shutdown<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
+       pub fn shutdown<F: Deref>(&mut self, fee_estimator: &F, their_features: &InitFeatures, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
                where F::Target: FeeEstimator
        {
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
@@ -3085,14 +3090,7 @@ impl<Signer: Sign> Channel<Signer> {
                }
                assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
 
-               // BOLT 2 says we must only send a scriptpubkey of certain standard forms, which are up to
-               // 34 bytes in length, so don't let the remote peer feed us some super fee-heavy script.
-               if self.is_outbound() && msg.scriptpubkey.len() > 34 {
-                       return Err(ChannelError::Close(format!("Got counterparty shutdown_scriptpubkey ({}) of absurd length from remote peer", msg.scriptpubkey.to_bytes().to_hex())));
-               }
-
-               //Check counterparty_shutdown_scriptpubkey form as BOLT says we must
-               if !msg.scriptpubkey.is_p2pkh() && !msg.scriptpubkey.is_p2sh() && !msg.scriptpubkey.is_v0_p2wpkh() && !msg.scriptpubkey.is_v0_p2wsh() {
+               if is_unsupported_shutdown_script(&their_features, &msg.scriptpubkey) {
                        return Err(ChannelError::Close(format!("Got a nonstandard scriptpubkey ({}) from remote peer", msg.scriptpubkey.to_bytes().to_hex())));
                }
 
@@ -4089,7 +4087,8 @@ impl<Signer: Sign> Channel<Signer> {
                        signature = res.0;
                        htlc_signatures = res.1;
 
-                       log_trace!(logger, "Signed remote commitment tx {} with redeemscript {} -> {}",
+                       log_trace!(logger, "Signed remote commitment tx {} (txid {}) with redeemscript {} -> {}",
+                               encode::serialize_hex(&counterparty_commitment_tx.0.trust().built_transaction().transaction),
                                &counterparty_commitment_txid,
                                encode::serialize_hex(&self.get_funding_redeemscript()),
                                log_bytes!(signature.serialize_compact()[..]));
@@ -4217,6 +4216,24 @@ impl<Signer: Sign> Channel<Signer> {
        }
 }
 
+fn is_unsupported_shutdown_script(their_features: &InitFeatures, script: &Script) -> bool {
+       // We restrain shutdown scripts to standards forms to avoid transactions not propagating on the p2p tx-relay network
+
+       // BOLT 2 says we must only send a scriptpubkey of certain standard forms,
+       // which for a a BIP-141-compliant witness program is at max 42 bytes in length.
+       // So don't let the remote peer feed us some super fee-heavy script.
+       let is_script_too_long = script.len() > 42;
+       if is_script_too_long {
+               return true;
+       }
+
+       if their_features.supports_shutdown_anysegwit() && script.is_witness_program() && script.as_bytes()[0] != OP_PUSHBYTES_0.into_u8() {
+               return false;
+       }
+
+       return !script.is_p2pkh() && !script.is_p2sh() && !script.is_v0_p2wpkh() && !script.is_v0_p2wsh()
+}
+
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
@@ -4598,13 +4615,16 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
                let counterparty_shutdown_scriptpubkey = Readable::read(reader)?;
                let commitment_secrets = Readable::read(reader)?;
 
+               let mut secp_ctx = Secp256k1::new();
+               secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes());
+
                Ok(Channel {
                        user_id,
 
                        config,
                        channel_id,
                        channel_state,
-                       secp_ctx: Secp256k1::new(),
+                       secp_ctx,
                        channel_value_satoshis,
 
                        latest_monitor_update_id,