From 1d3861e5f6a543d882905ebda21656cc0ea231a7 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Sun, 1 Aug 2021 22:31:07 -0500 Subject: [PATCH] Add APIError::IncompatibleShutdownScript --- fuzz/src/chanmon_consistency.rs | 1 + lightning/src/ln/channel.rs | 14 ++++++++------ lightning/src/ln/functional_tests.rs | 4 +++- lightning/src/util/errors.rs | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index f26b3bf5..ef9ce82d 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -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] diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index d5f066c4..b678f0f4 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -607,8 +607,8 @@ impl Channel { } 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 Channel { 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::::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"), diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index f22df683..1d149b83 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -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"), } diff --git a/lightning/src/util/errors.rs b/lightning/src/util/errors.rs index ddcc693b..94ad9656 100644 --- a/lightning/src/util/errors.rs +++ b/lightning/src/util/errors.rs @@ -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) + }, } } } -- 2.30.2