]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Enforce segwit inputs for all "safe" funding transactions 2024-07-funding-check
authorMatt Corallo <git@bluematt.me>
Mon, 22 Jul 2024 20:03:41 +0000 (20:03 +0000)
committerMatt Corallo <git@bluematt.me>
Mon, 22 Jul 2024 20:03:41 +0000 (20:03 +0000)
8403755a2a524beb9f6c8951f51dd60f7c54c912 introduced a separate path
for funding a channel without a full funding transaction, relying
on users to manually broadcast the funding tx. One of the major
things that makes this path less safe is that for other paths we're
supposed to validate that all inputs have witnesses, making the
funding transaction (likely) txid-non-malleable.

However, in one of several rewrites of that commit the funding tx
tests ended up getting elided in some call paths, which is fixed
here.

lightning/src/ln/channelmanager.rs

index 9bceb5816b63db64c9d1d3db116b5735ac4afa99..893595ce12a7f6116cc8cf9aa9457a86745f0c56 100644 (file)
@@ -4605,23 +4605,22 @@ where
        /// If there is an error, all channels in the batch are to be considered closed.
        pub fn batch_funding_transaction_generated(&self, temporary_channels: &[(&ChannelId, &PublicKey)], funding_transaction: Transaction) -> Result<(), APIError> {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
-               let mut result = Ok(());
-
-               if !funding_transaction.is_coinbase() {
-                       for inp in funding_transaction.input.iter() {
-                               if inp.witness.is_empty() {
-                                       result = result.and(Err(APIError::APIMisuseError {
-                                               err: "Funding transaction must be fully signed and spend Segwit outputs".to_owned()
-                                       }));
-                               }
-                       }
-               }
-               result.and(self.batch_funding_transaction_generated_intern(temporary_channels, FundingType::Checked(funding_transaction)))
+               self.batch_funding_transaction_generated_intern(temporary_channels, FundingType::Checked(funding_transaction))
        }
 
        fn batch_funding_transaction_generated_intern(&self, temporary_channels: &[(&ChannelId, &PublicKey)], funding: FundingType) -> Result<(), APIError> {
                let mut result = Ok(());
                if let FundingType::Checked(funding_transaction) = &funding {
+                       if !funding_transaction.is_coinbase() {
+                               for inp in funding_transaction.input.iter() {
+                                       if inp.witness.is_empty() {
+                                               result = result.and(Err(APIError::APIMisuseError {
+                                                       err: "Funding transaction must be fully signed and spend Segwit outputs".to_owned()
+                                               }));
+                                       }
+                               }
+                       }
+
                        if funding_transaction.output.len() > u16::max_value() as usize {
                                result = result.and(Err(APIError::APIMisuseError {
                                        err: "Transaction had more than 2^16 outputs, which is not supported".to_owned()