Add APIError::IncompatibleShutdownScript
authorJeffrey Czyz <jkczyz@gmail.com>
Mon, 2 Aug 2021 03:31:07 +0000 (22:31 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Mon, 9 Aug 2021 20:56:29 +0000 (15:56 -0500)
fuzz/src/chanmon_consistency.rs
lightning/src/ln/channel.rs
lightning/src/ln/functional_tests.rs
lightning/src/util/errors.rs

index f26b3bf547964e66f9437cc8b52f6922a4490507..ef9ce82d0e28803aff4d0080f3c7491e2f2a8b7d 100644 (file)
@@ -253,6 +253,7 @@ fn check_api_err(api_err: APIError) {
                APIError::MonitorUpdateFailed => {
                        // We can (obviously) temp-fail a monitor update
                },
+               APIError::IncompatibleShutdownScript { .. } => panic!("Cannot send an incompatible shutdown script"),
        }
 }
 #[inline]
index d5f066c408021c96c1d13e1fa9ae9aaedca9b255..b678f0f46d798522083dcb145636980899880374 100644 (file)
@@ -607,8 +607,8 @@ impl<Signer: Sign> Channel<Signer> {
                } 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: {}", shutdown_scriptpubkey) });
+                       if !shutdown_scriptpubkey.is_compatible(&their_features) {
+                               return Err(APIError::IncompatibleShutdownScript { script: shutdown_scriptpubkey.clone() });
                        }
                }
 
@@ -4487,7 +4487,7 @@ impl<Signer: Sign> Channel<Signer> {
                        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: {}", shutdown_scriptpubkey) });
+                                       return Err(APIError::IncompatibleShutdownScript { script: shutdown_scriptpubkey.clone() });
                                }
                                self.shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
                                true
@@ -5253,15 +5253,17 @@ mod tests {
                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 });
+               keys_provider.expect(OnGetShutdownScriptpubkey {
+                       returns: non_v0_segwit_shutdown_script.clone(),
+               });
 
                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(APIError::IncompatibleShutdownScript { script }) => {
+                               assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner());
                        },
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok(_) => panic!("Expected error"),
index f22df683247edb7e364713efa9eebf2387e4600c..1d149b83703393b502b5987e2bd920bf9c788908 100644 (file)
@@ -7693,7 +7693,9 @@ fn test_unsupported_anysegwit_shutdown_script() {
 
        let chan = create_announced_chan_between_nodes(&nodes, 0, 1, node_cfgs[0].features.clone(), node_cfgs[1].features.clone());
        match nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()) {
-               Err(APIError::APIMisuseError { err }) => assert_eq!(err, "Provided a scriptpubkey format not accepted by peer. script: (60020028)"),
+               Err(APIError::IncompatibleShutdownScript { script }) => {
+                       assert_eq!(script.into_inner(), unsupported_shutdown_script.clone().into_inner());
+               },
                Err(e) => panic!("Unexpected error: {:?}", e),
                Ok(_) => panic!("Expected error"),
        }
index ddcc693b3398e969b364c89b4ee4a73684d33153..94ad965667873aa0b8f66d2e06427a491547e611 100644 (file)
@@ -9,6 +9,8 @@
 
 //! Error types live here.
 
+use ln::script::ShutdownScript;
+
 use alloc::string::String;
 use core::fmt;
 
@@ -47,6 +49,18 @@ pub enum APIError {
        /// An attempt to call watch/update_channel returned an Err (ie you did this!), causing the
        /// attempted action to fail.
        MonitorUpdateFailed,
+       /// [`KeysInterface::get_shutdown_scriptpubkey`] returned a shutdown scriptpubkey incompatible
+       /// with the channel counterparty as negotiated in [`InitFeatures`].
+       ///
+       /// Using a SegWit v0 script should resolve this issue. If you cannot, you won't be able to open
+       /// a channel or cooperatively close one with this peer (and will have to force-close instead).
+       ///
+       /// [`KeysInterface::get_shutdown_scriptpubkey`]: crate::chain::keysinterface::KeysInterface::get_shutdown_scriptpubkey
+       /// [`InitFeatures`]: crate::ln::features::InitFeatures
+       IncompatibleShutdownScript {
+               /// The incompatible shutdown script.
+               script: ShutdownScript,
+       },
 }
 
 impl fmt::Debug for APIError {
@@ -57,6 +71,9 @@ impl fmt::Debug for APIError {
                        APIError::RouteError {ref err} => f.write_str(err),
                        APIError::ChannelUnavailable {ref err} => f.write_str(err),
                        APIError::MonitorUpdateFailed => f.write_str("Client indicated a channel monitor update failed"),
+                       APIError::IncompatibleShutdownScript { ref script } => {
+                               write!(f, "Provided a scriptpubkey format not accepted by peer: {}", script)
+                       },
                }
        }
 }