Generate shutdown script at channel close
[rust-lightning] / lightning / src / ln / channel.rs
index 9f768d1535a168660b368611163decf26aa6ebc2..5f8236608c196ea4634a2a4538aa10f252b6fa88 100644 (file)
@@ -574,7 +574,7 @@ impl<Signer: Sign> Channel<Signer> {
        }
 
        // Constructors:
-       pub fn new_outbound<K: Deref, F: Deref>(fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig) -> Result<Channel<Signer>, APIError>
+       pub fn new_outbound<K: Deref, F: Deref>(fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: InitFeatures, channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig) -> Result<Channel<Signer>, APIError>
        where K::Target: KeysInterface<Signer = Signer>,
              F::Target: FeeEstimator,
        {
@@ -602,6 +602,16 @@ impl<Signer: Sign> Channel<Signer> {
                let mut secp_ctx = Secp256k1::new();
                secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
 
+               let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
+                       Some(keys_provider.get_shutdown_scriptpubkey())
+               } else { None };
+
+               if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey {
+                       if !shutdown_scriptpubkey.is_compatible(&their_features) {
+                               return Err(APIError::APIMisuseError { err: format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex()) });
+                       }
+               }
+
                Ok(Channel {
                        user_id,
                        config: config.channel_options.clone(),
@@ -614,7 +624,7 @@ impl<Signer: Sign> Channel<Signer> {
                        latest_monitor_update_id: 0,
 
                        holder_signer,
-                       shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
+                       shutdown_scriptpubkey,
                        destination_script: keys_provider.get_destination_script(),
 
                        cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -844,6 +854,16 @@ impl<Signer: Sign> Channel<Signer> {
                        }
                } else { None };
 
+               let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
+                       Some(keys_provider.get_shutdown_scriptpubkey())
+               } else { None };
+
+               if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey {
+                       if !shutdown_scriptpubkey.is_compatible(&their_features) {
+                               return Err(ChannelError::Close(format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex())));
+                       }
+               }
+
                let mut secp_ctx = Secp256k1::new();
                secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
 
@@ -858,7 +878,7 @@ impl<Signer: Sign> Channel<Signer> {
                        latest_monitor_update_id: 0,
 
                        holder_signer,
-                       shutdown_scriptpubkey: Some(keys_provider.get_shutdown_scriptpubkey()),
+                       shutdown_scriptpubkey,
                        destination_script: keys_provider.get_destination_script(),
 
                        cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
@@ -1206,6 +1226,7 @@ impl<Signer: Sign> Channel<Signer> {
                        }, ()));
                }
 
+               assert!(self.shutdown_scriptpubkey.is_some());
                if value_to_self as u64 > self.holder_dust_limit_satoshis {
                        txouts.push((TxOut {
                                script_pubkey: self.get_closing_scriptpubkey(),
@@ -3096,6 +3117,7 @@ impl<Signer: Sign> Channel<Signer> {
                self.channel_state &= !(ChannelState::PeerDisconnected as u32);
 
                let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 {
+                       assert!(self.shutdown_scriptpubkey.is_some());
                        Some(msgs::Shutdown {
                                channel_id: self.channel_id,
                                scriptpubkey: self.get_closing_scriptpubkey(),
@@ -3207,6 +3229,7 @@ impl<Signer: Sign> Channel<Signer> {
                if self.feerate_per_kw > proposed_feerate {
                        proposed_feerate = self.feerate_per_kw;
                }
+               assert!(self.shutdown_scriptpubkey.is_some());
                let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
                let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
 
@@ -3225,8 +3248,12 @@ impl<Signer: Sign> Channel<Signer> {
                })
        }
 
-       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
+       pub fn shutdown<F: Deref, K: Deref>(
+               &mut self, fee_estimator: &F, keys_provider: &K, their_features: &InitFeatures, msg: &msgs::Shutdown
+       ) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
+       where
+               F::Target: FeeEstimator,
+               K::Target: KeysInterface<Signer = Signer>
        {
                if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
                        return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish".to_owned()));
@@ -3257,11 +3284,45 @@ impl<Signer: Sign> Channel<Signer> {
                        self.counterparty_shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
                }
 
+               // If we have any LocalAnnounced updates we'll probably just get back an update_fail_htlc
+               // immediately after the commitment dance, but we can send a Shutdown because we won't send
+               // any further commitment updates after we set LocalShutdownSent.
+               let send_shutdown = (self.channel_state & ChannelState::LocalShutdownSent as u32) != ChannelState::LocalShutdownSent as u32;
+
+               let update_shutdown_script = match self.shutdown_scriptpubkey {
+                       Some(_) => false,
+                       None => {
+                               assert!(send_shutdown);
+                               let shutdown_scriptpubkey = keys_provider.get_shutdown_scriptpubkey();
+                               if !shutdown_scriptpubkey.is_compatible(their_features) {
+                                       return Err(ChannelError::Close(format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex())));
+                               }
+                               self.shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
+                               true
+                       },
+               };
+
                // From here on out, we may not fail!
 
                self.channel_state |= ChannelState::RemoteShutdownSent as u32;
                self.update_time_counter += 1;
 
+               let monitor_update = if update_shutdown_script {
+                       self.latest_monitor_update_id += 1;
+                       Some(ChannelMonitorUpdate {
+                               update_id: self.latest_monitor_update_id,
+                               updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
+                                       scriptpubkey: self.get_closing_scriptpubkey(),
+                               }],
+                       })
+               } else { None };
+               let shutdown = if send_shutdown {
+                       Some(msgs::Shutdown {
+                               channel_id: self.channel_id,
+                               scriptpubkey: self.get_closing_scriptpubkey(),
+                       })
+               } else { None };
+
                // We can't send our shutdown until we've committed all of our pending HTLCs, but the
                // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding
                // cell HTLCs and return them to fail the payment.
@@ -3276,23 +3337,11 @@ impl<Signer: Sign> Channel<Signer> {
                                _ => true
                        }
                });
-               // If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc
-               // immediately after the commitment dance, but we can send a Shutdown cause we won't send
-               // any further commitment updates after we set LocalShutdownSent.
-
-               let shutdown = if (self.channel_state & ChannelState::LocalShutdownSent as u32) == ChannelState::LocalShutdownSent as u32 {
-                       None
-               } else {
-                       Some(msgs::Shutdown {
-                               channel_id: self.channel_id,
-                               scriptpubkey: self.get_closing_scriptpubkey(),
-                       })
-               };
 
                self.channel_state |= ChannelState::LocalShutdownSent as u32;
                self.update_time_counter += 1;
 
-               Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
+               Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), monitor_update, dropped_outbound_htlcs))
        }
 
        fn build_signed_closing_transaction(&self, tx: &mut Transaction, counterparty_sig: &Signature, sig: &Signature) {
@@ -3367,6 +3416,7 @@ impl<Signer: Sign> Channel<Signer> {
 
                macro_rules! propose_new_feerate {
                        ($new_feerate: expr) => {
+                               assert!(self.shutdown_scriptpubkey.is_some());
                                let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
                                let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate as u64 * tx_weight / 1000, false);
                                let sig = self.holder_signer
@@ -3865,7 +3915,10 @@ impl<Signer: Sign> Channel<Signer> {
                        htlc_basepoint: keys.htlc_basepoint,
                        first_per_commitment_point,
                        channel_flags: if self.config.announced_channel {1} else {0},
-                       shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() })
+                       shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
+                               Some(script) => script.clone().into_inner(),
+                               None => Builder::new().into_script(),
+                       }),
                }
        }
 
@@ -3898,7 +3951,10 @@ impl<Signer: Sign> Channel<Signer> {
                        delayed_payment_basepoint: keys.delayed_payment_basepoint,
                        htlc_basepoint: keys.htlc_basepoint,
                        first_per_commitment_point,
-                       shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() })
+                       shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
+                               Some(script) => script.clone().into_inner(),
+                               None => Builder::new().into_script(),
+                       }),
                }
        }
 
@@ -4406,7 +4462,8 @@ impl<Signer: Sign> Channel<Signer> {
 
        /// Begins the shutdown process, getting a message for the remote peer and returning all
        /// holding cell HTLCs for payment failure.
-       pub fn get_shutdown(&mut self) -> Result<(msgs::Shutdown, Vec<(HTLCSource, PaymentHash)>), APIError> {
+       pub fn get_shutdown<K: Deref>(&mut self, keys_provider: &K, their_features: &InitFeatures) -> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
+       where K::Target: KeysInterface<Signer = Signer> {
                for htlc in self.pending_outbound_htlcs.iter() {
                        if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
                                return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()});
@@ -4425,7 +4482,17 @@ impl<Signer: Sign> Channel<Signer> {
                        return Err(APIError::ChannelUnavailable{err: "Cannot begin shutdown while peer is disconnected or we're waiting on a monitor update, maybe force-close instead?".to_owned()});
                }
 
-               let closing_script = self.get_closing_scriptpubkey();
+               let update_shutdown_script = match self.shutdown_scriptpubkey {
+                       Some(_) => false,
+                       None => {
+                               let shutdown_scriptpubkey = keys_provider.get_shutdown_scriptpubkey();
+                               if !shutdown_scriptpubkey.is_compatible(their_features) {
+                                       return Err(APIError::APIMisuseError { err: format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex()) });
+                               }
+                               self.shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
+                               true
+                       },
+               };
 
                // From here on out, we may not fail!
                if self.channel_state < ChannelState::FundingSent as u32 {
@@ -4435,6 +4502,20 @@ impl<Signer: Sign> Channel<Signer> {
                }
                self.update_time_counter += 1;
 
+               let monitor_update = if update_shutdown_script {
+                       self.latest_monitor_update_id += 1;
+                       Some(ChannelMonitorUpdate {
+                               update_id: self.latest_monitor_update_id,
+                               updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
+                                       scriptpubkey: self.get_closing_scriptpubkey(),
+                               }],
+                       })
+               } else { None };
+               let shutdown = msgs::Shutdown {
+                       channel_id: self.channel_id,
+                       scriptpubkey: self.get_closing_scriptpubkey(),
+               };
+
                // Go ahead and drop holding cell updates as we'd rather fail payments than wait to send
                // our shutdown until we've committed all of the pending changes.
                self.holding_cell_update_fee = None;
@@ -4449,10 +4530,7 @@ impl<Signer: Sign> Channel<Signer> {
                        }
                });
 
-               Ok((msgs::Shutdown {
-                       channel_id: self.channel_id,
-                       scriptpubkey: closing_script,
-               }, dropped_outbound_htlcs))
+               Ok((shutdown, monitor_update, dropped_outbound_htlcs))
        }
 
        /// Gets the latest commitment transaction and any dependent transactions for relay (forcing
@@ -5104,7 +5182,9 @@ mod tests {
        use chain::transaction::OutPoint;
        use util::config::UserConfig;
        use util::enforcing_trait_impls::EnforcingSigner;
+       use util::errors::APIError;
        use util::test_utils;
+       use util::test_utils::OnGetShutdownScriptpubkey;
        use util::logger::Logger;
        use bitcoin::secp256k1::{Secp256k1, Message, Signature, All};
        use bitcoin::secp256k1::ffi::Signature as FFISignature;
@@ -5113,6 +5193,7 @@ mod tests {
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::Hash;
        use bitcoin::hash_types::{Txid, WPubkeyHash};
+       use core::num::NonZeroU8;
        use sync::Arc;
        use prelude::*;
 
@@ -5163,6 +5244,30 @@ mod tests {
                PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap())
        }
 
+       #[test]
+       fn upfront_shutdown_script_incompatibility() {
+               let features = InitFeatures::known().clear_shutdown_anysegwit();
+               let non_v0_segwit_shutdown_script =
+                       ShutdownScript::new_witness_program(NonZeroU8::new(16).unwrap(), &[0, 40]).unwrap();
+
+               let seed = [42; 32];
+               let network = Network::Testnet;
+               let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
+               keys_provider.expect(OnGetShutdownScriptpubkey { returns: non_v0_segwit_shutdown_script });
+
+               let fee_estimator = TestFeeEstimator { fee_est: 253 };
+               let secp_ctx = Secp256k1::new();
+               let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let config = UserConfig::default();
+               match Channel::<EnforcingSigner>::new_outbound(&&fee_estimator, &&keys_provider, node_id, features, 10000000, 100000, 42, &config) {
+                       Err(APIError::APIMisuseError { err }) => {
+                               assert_eq!(err, "Provided a scriptpubkey format not accepted by peer. script: (60020028)");
+                       },
+                       Err(e) => panic!("Unexpected error: {:?}", e),
+                       Ok(_) => panic!("Expected error"),
+               }
+       }
+
        // Check that, during channel creation, we use the same feerate in the open channel message
        // as we do in the Channel object creation itself.
        #[test]
@@ -5176,7 +5281,7 @@ mod tests {
 
                let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, 10000000, 100000, 42, &config).unwrap();
+               let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
 
                // Now change the fee so we can check that the fee in the open_channel message is the
                // same as the old fee.
@@ -5201,7 +5306,7 @@ mod tests {
                // Create Node A's channel pointing to Node B's pubkey
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap();
+               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
 
                // Create Node B's channel by receiving Node A's open_channel message
                // Make sure A's dust limit is as we expect.
@@ -5268,7 +5373,7 @@ mod tests {
 
                let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, 10000000, 100000, 42, &config).unwrap();
+               let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
 
                let commitment_tx_fee_0_htlcs = chan.commit_tx_fee_msat(0);
                let commitment_tx_fee_1_htlc = chan.commit_tx_fee_msat(1);
@@ -5317,7 +5422,7 @@ mod tests {
                // Create Node A's channel pointing to Node B's pubkey
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap();
+               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
 
                // Create Node B's channel by receiving Node A's open_channel message
                let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
@@ -5379,7 +5484,7 @@ mod tests {
                // Create a channel.
                let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let config = UserConfig::default();
-               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap();
+               let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
                assert!(node_a_chan.counterparty_forwarding_info.is_none());
                assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default
                assert!(node_a_chan.counterparty_forwarding_info().is_none());
@@ -5443,7 +5548,7 @@ mod tests {
                let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let mut config = UserConfig::default();
                config.channel_options.announced_channel = false;
-               let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, 10_000_000, 100000, 42, &config).unwrap(); // Nothing uses their network key in this test
+               let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, InitFeatures::known(), 10_000_000, 100000, 42, &config).unwrap(); // Nothing uses their network key in this test
                chan.holder_dust_limit_satoshis = 546;
                chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel