Move inbound channel methods into `InboundV1Channel`'s impl
authorDuncan Dean <git@dunxen.dev>
Wed, 7 Jun 2023 16:14:59 +0000 (18:14 +0200)
committerDuncan Dean <git@dunxen.dev>
Thu, 15 Jun 2023 20:31:37 +0000 (22:31 +0200)
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs

index e1f3e85ff468376a8c0498ff3725018568c2d764..7da903f4e0c2f33b20d7cf3973acf65fe24b3aac 100644 (file)
@@ -2010,8 +2010,6 @@ struct CommitmentTxInfoCached {
 }
 
 impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
-       // Constructors:
-
        fn check_remote_fee<F: Deref, L: Deref>(fee_estimator: &LowerBoundedFeeEstimator<F>,
                feerate_per_kw: u32, cur_feerate_per_kw: Option<u32>, logger: &L)
                -> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger,
@@ -2422,129 +2420,6 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
        // Message handlers:
 
-       fn funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<(Txid, CommitmentTransaction, Signature), ChannelError> where L::Target: Logger {
-               let funding_script = self.context.get_funding_redeemscript();
-
-               let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
-               let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger).tx;
-               {
-                       let trusted_tx = initial_commitment_tx.trust();
-                       let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
-                       let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis);
-                       // They sign the holder commitment transaction...
-                       log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
-                               log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.context.counterparty_funding_pubkey().serialize()),
-                               encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
-                               encode::serialize_hex(&funding_script), log_bytes!(self.context.channel_id()));
-                       secp_check!(self.context.secp_ctx.verify_ecdsa(&sighash, &sig, self.context.counterparty_funding_pubkey()), "Invalid funding_created signature from peer".to_owned());
-               }
-
-               let counterparty_keys = self.context.build_remote_transaction_keys();
-               let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
-
-               let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
-               let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
-               log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}",
-                       log_bytes!(self.context.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction));
-
-               let counterparty_signature = self.context.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
-                               .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0;
-
-               // We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish.
-               Ok((counterparty_initial_bitcoin_tx.txid, initial_commitment_tx, counterparty_signature))
-       }
-
-       pub fn funding_created<SP: Deref, L: Deref>(
-               &mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L
-       ) -> Result<(msgs::FundingSigned, ChannelMonitor<Signer>), ChannelError>
-       where
-               SP::Target: SignerProvider<Signer = Signer>,
-               L::Target: Logger
-       {
-               if self.context.is_outbound() {
-                       return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned()));
-               }
-               if self.context.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) {
-                       // BOLT 2 says that if we disconnect before we send funding_signed we SHOULD NOT
-                       // remember the channel, so it's safe to just send an error_message here and drop the
-                       // channel.
-                       return Err(ChannelError::Close("Received funding_created after we got the channel!".to_owned()));
-               }
-               if self.context.inbound_awaiting_accept {
-                       return Err(ChannelError::Close("FundingCreated message received before the channel was accepted".to_owned()));
-               }
-               if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
-                               self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
-                               self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
-                       panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
-               }
-
-               let funding_txo = OutPoint { txid: msg.funding_txid, index: msg.funding_output_index };
-               self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
-               // This is an externally observable change before we finish all our checks.  In particular
-               // funding_created_signature may fail.
-               self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
-
-               let (counterparty_initial_commitment_txid, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
-                       Ok(res) => res,
-                       Err(ChannelError::Close(e)) => {
-                               self.context.channel_transaction_parameters.funding_outpoint = None;
-                               return Err(ChannelError::Close(e));
-                       },
-                       Err(e) => {
-                               // The only error we know how to handle is ChannelError::Close, so we fall over here
-                               // to make sure we don't continue with an inconsistent state.
-                               panic!("unexpected error type from funding_created_signature {:?}", e);
-                       }
-               };
-
-               let holder_commitment_tx = HolderCommitmentTransaction::new(
-                       initial_commitment_tx,
-                       msg.signature,
-                       Vec::new(),
-                       &self.context.get_holder_pubkeys().funding_pubkey,
-                       self.context.counterparty_funding_pubkey()
-               );
-
-               self.context.holder_signer.validate_holder_commitment(&holder_commitment_tx, Vec::new())
-                       .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?;
-
-                       // Now that we're past error-generating stuff, update our local state:
-
-               let funding_redeemscript = self.context.get_funding_redeemscript();
-               let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
-               let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound());
-               let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
-               let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id);
-               monitor_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
-               let channel_monitor = ChannelMonitor::new(self.context.secp_ctx.clone(), monitor_signer,
-                                                         shutdown_script, self.context.get_holder_selected_contest_delay(),
-                                                         &self.context.destination_script, (funding_txo, funding_txo_script.clone()),
-                                                         &self.context.channel_transaction_parameters,
-                                                         funding_redeemscript.clone(), self.context.channel_value_satoshis,
-                                                         obscure_factor,
-                                                         holder_commitment_tx, best_block, self.context.counterparty_node_id);
-
-               channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.context.cur_counterparty_commitment_transaction_number, self.context.counterparty_cur_commitment_point.unwrap(), logger);
-
-               self.context.channel_state = ChannelState::FundingSent as u32;
-               self.context.channel_id = funding_txo.to_channel_id();
-               self.context.cur_counterparty_commitment_transaction_number -= 1;
-               self.context.cur_holder_commitment_transaction_number -= 1;
-
-               log_info!(logger, "Generated funding_signed for peer for channel {}", log_bytes!(self.context.channel_id()));
-
-               let need_channel_ready = self.check_get_channel_ready(0).is_some();
-               self.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
-
-               Ok((msgs::FundingSigned {
-                       channel_id: self.context.channel_id,
-                       signature,
-                       #[cfg(taproot)]
-                       partial_signature_with_nonce: None,
-               }, channel_monitor))
-       }
-
        /// Handles a funding_signed message from the remote end.
        /// If this call is successful, broadcast the funding transaction (and not before!)
        pub fn funding_signed<SP: Deref, L: Deref>(
@@ -4938,83 +4813,6 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
        // Methods to get unprompted messages to send to the remote end (or where we already returned
        // something in the handler for the message that prompted this message):
 
-       pub fn inbound_is_awaiting_accept(&self) -> bool {
-               self.context.inbound_awaiting_accept
-       }
-
-       /// Sets this channel to accepting 0conf, must be done before `get_accept_channel`
-       pub fn set_0conf(&mut self) {
-               assert!(self.context.inbound_awaiting_accept);
-               self.context.minimum_depth = Some(0);
-       }
-
-       /// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannel`] message which
-       /// should be sent back to the counterparty node.
-       ///
-       /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
-       pub fn accept_inbound_channel(&mut self, user_id: u128) -> msgs::AcceptChannel {
-               if self.context.is_outbound() {
-                       panic!("Tried to send accept_channel for an outbound channel?");
-               }
-               if self.context.channel_state != (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32) {
-                       panic!("Tried to send accept_channel after channel had moved forward");
-               }
-               if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
-                       panic!("Tried to send an accept_channel for a channel that has already advanced");
-               }
-               if !self.context.inbound_awaiting_accept {
-                       panic!("The inbound channel has already been accepted");
-               }
-
-               self.context.user_id = user_id;
-               self.context.inbound_awaiting_accept = false;
-
-               self.generate_accept_channel_message()
-       }
-
-       /// This function is used to explicitly generate a [`msgs::AcceptChannel`] message for an
-       /// inbound channel. If the intention is to accept an inbound channel, use
-       /// [`Channel::accept_inbound_channel`] instead.
-       ///
-       /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
-       fn generate_accept_channel_message(&self) -> msgs::AcceptChannel {
-               let first_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
-               let keys = self.context.get_holder_pubkeys();
-
-               msgs::AcceptChannel {
-                       temporary_channel_id: self.context.channel_id,
-                       dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
-                       max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
-                       channel_reserve_satoshis: self.context.holder_selected_channel_reserve_satoshis,
-                       htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
-                       minimum_depth: self.context.minimum_depth.unwrap(),
-                       to_self_delay: self.context.get_holder_selected_contest_delay(),
-                       max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
-                       funding_pubkey: keys.funding_pubkey,
-                       revocation_basepoint: keys.revocation_basepoint,
-                       payment_point: keys.payment_point,
-                       delayed_payment_basepoint: keys.delayed_payment_basepoint,
-                       htlc_basepoint: keys.htlc_basepoint,
-                       first_per_commitment_point,
-                       shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
-                               Some(script) => script.clone().into_inner(),
-                               None => Builder::new().into_script(),
-                       }),
-                       channel_type: Some(self.context.channel_type.clone()),
-                       #[cfg(taproot)]
-                       next_local_nonce: None,
-               }
-       }
-
-       /// Enables the possibility for tests to extract a [`msgs::AcceptChannel`] message for an
-       /// inbound channel without accepting it.
-       ///
-       /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
-       #[cfg(test)]
-       pub fn get_accept_channel_message(&self) -> msgs::AcceptChannel {
-               self.generate_accept_channel_message()
-       }
-
        /// Gets an UnsignedChannelAnnouncement for this channel. The channel must be publicly
        /// announceable and available for use (have exchanged ChannelReady messages in both
        /// directions). Should be used for both broadcasted announcements and in response to an
@@ -6142,7 +5940,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
                counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
                their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig,
                current_chain_height: u32, logger: &L, outbound_scid_alias: u64
-       ) -> Result<Channel<Signer>, ChannelError>
+       ) -> Result<InboundV1Channel<Signer>, ChannelError>
                where ES::Target: EntropySource,
                          SP::Target: SignerProvider<Signer = Signer>,
                          F::Target: FeeEstimator,
@@ -6332,7 +6130,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
                let mut secp_ctx = Secp256k1::new();
                secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
 
-               let chan = Channel {
+               let chan = Self {
                        context: ChannelContext {
                                user_id,
 
@@ -6466,6 +6264,213 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
 
                Ok(chan)
        }
+
+       pub fn inbound_is_awaiting_accept(&self) -> bool {
+               self.context.inbound_awaiting_accept
+       }
+
+       /// Sets this channel to accepting 0conf, must be done before `get_accept_channel`
+       pub fn set_0conf(&mut self) {
+               assert!(self.context.inbound_awaiting_accept);
+               self.context.minimum_depth = Some(0);
+       }
+
+       /// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannel`] message which
+       /// should be sent back to the counterparty node.
+       ///
+       /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
+       pub fn accept_inbound_channel(&mut self, user_id: u128) -> msgs::AcceptChannel {
+               if self.context.is_outbound() {
+                       panic!("Tried to send accept_channel for an outbound channel?");
+               }
+               if self.context.channel_state != (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32) {
+                       panic!("Tried to send accept_channel after channel had moved forward");
+               }
+               if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+                       panic!("Tried to send an accept_channel for a channel that has already advanced");
+               }
+               if !self.context.inbound_awaiting_accept {
+                       panic!("The inbound channel has already been accepted");
+               }
+
+               self.context.user_id = user_id;
+               self.context.inbound_awaiting_accept = false;
+
+               self.generate_accept_channel_message()
+       }
+
+       /// This function is used to explicitly generate a [`msgs::AcceptChannel`] message for an
+       /// inbound channel. If the intention is to accept an inbound channel, use
+       /// [`InboundV1Channel::accept_inbound_channel`] instead.
+       ///
+       /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
+       fn generate_accept_channel_message(&self) -> msgs::AcceptChannel {
+               let first_per_commitment_point = self.context.holder_signer.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
+               let keys = self.context.get_holder_pubkeys();
+
+               msgs::AcceptChannel {
+                       temporary_channel_id: self.context.channel_id,
+                       dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
+                       max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
+                       channel_reserve_satoshis: self.context.holder_selected_channel_reserve_satoshis,
+                       htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
+                       minimum_depth: self.context.minimum_depth.unwrap(),
+                       to_self_delay: self.context.get_holder_selected_contest_delay(),
+                       max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
+                       funding_pubkey: keys.funding_pubkey,
+                       revocation_basepoint: keys.revocation_basepoint,
+                       payment_point: keys.payment_point,
+                       delayed_payment_basepoint: keys.delayed_payment_basepoint,
+                       htlc_basepoint: keys.htlc_basepoint,
+                       first_per_commitment_point,
+                       shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
+                               Some(script) => script.clone().into_inner(),
+                               None => Builder::new().into_script(),
+                       }),
+                       channel_type: Some(self.context.channel_type.clone()),
+                       #[cfg(taproot)]
+                       next_local_nonce: None,
+               }
+       }
+
+       /// Enables the possibility for tests to extract a [`msgs::AcceptChannel`] message for an
+       /// inbound channel without accepting it.
+       ///
+       /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
+       #[cfg(test)]
+       pub fn get_accept_channel_message(&self) -> msgs::AcceptChannel {
+               self.generate_accept_channel_message()
+       }
+
+       fn funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<(Txid, CommitmentTransaction, Signature), ChannelError> where L::Target: Logger {
+               let funding_script = self.context.get_funding_redeemscript();
+
+               let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
+               let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger).tx;
+               {
+                       let trusted_tx = initial_commitment_tx.trust();
+                       let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
+                       let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis);
+                       // They sign the holder commitment transaction...
+                       log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
+                               log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.context.counterparty_funding_pubkey().serialize()),
+                               encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
+                               encode::serialize_hex(&funding_script), log_bytes!(self.context.channel_id()));
+                       secp_check!(self.context.secp_ctx.verify_ecdsa(&sighash, &sig, self.context.counterparty_funding_pubkey()), "Invalid funding_created signature from peer".to_owned());
+               }
+
+               let counterparty_keys = self.context.build_remote_transaction_keys();
+               let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
+
+               let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
+               let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
+               log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}",
+                       log_bytes!(self.context.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction));
+
+               let counterparty_signature = self.context.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
+                               .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0;
+
+               // We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish.
+               Ok((counterparty_initial_bitcoin_tx.txid, initial_commitment_tx, counterparty_signature))
+       }
+
+       pub fn funding_created<SP: Deref, L: Deref>(
+               mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L
+       ) -> Result<(Channel<Signer>, msgs::FundingSigned, ChannelMonitor<Signer>), (Self, ChannelError)>
+       where
+               SP::Target: SignerProvider<Signer = Signer>,
+               L::Target: Logger
+       {
+               if self.context.is_outbound() {
+                       return Err((self, ChannelError::Close("Received funding_created for an outbound channel?".to_owned())));
+               }
+               if self.context.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) {
+                       // BOLT 2 says that if we disconnect before we send funding_signed we SHOULD NOT
+                       // remember the channel, so it's safe to just send an error_message here and drop the
+                       // channel.
+                       return Err((self, ChannelError::Close("Received funding_created after we got the channel!".to_owned())));
+               }
+               if self.context.inbound_awaiting_accept {
+                       return Err((self, ChannelError::Close("FundingCreated message received before the channel was accepted".to_owned())));
+               }
+               if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
+                               self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
+                               self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+                       panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
+               }
+
+               let funding_txo = OutPoint { txid: msg.funding_txid, index: msg.funding_output_index };
+               self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
+               // This is an externally observable change before we finish all our checks.  In particular
+               // funding_created_signature may fail.
+               self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
+
+               let (counterparty_initial_commitment_txid, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
+                       Ok(res) => res,
+                       Err(ChannelError::Close(e)) => {
+                               self.context.channel_transaction_parameters.funding_outpoint = None;
+                               return Err((self, ChannelError::Close(e)));
+                       },
+                       Err(e) => {
+                               // The only error we know how to handle is ChannelError::Close, so we fall over here
+                               // to make sure we don't continue with an inconsistent state.
+                               panic!("unexpected error type from funding_created_signature {:?}", e);
+                       }
+               };
+
+               let holder_commitment_tx = HolderCommitmentTransaction::new(
+                       initial_commitment_tx,
+                       msg.signature,
+                       Vec::new(),
+                       &self.context.get_holder_pubkeys().funding_pubkey,
+                       self.context.counterparty_funding_pubkey()
+               );
+
+               if let Err(_) = self.context.holder_signer.validate_holder_commitment(&holder_commitment_tx, Vec::new()) {
+                       return Err((self, ChannelError::Close("Failed to validate our commitment".to_owned())));
+               }
+
+               // Now that we're past error-generating stuff, update our local state:
+
+               let funding_redeemscript = self.context.get_funding_redeemscript();
+               let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
+               let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound());
+               let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
+               let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id);
+               monitor_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
+               let channel_monitor = ChannelMonitor::new(self.context.secp_ctx.clone(), monitor_signer,
+                                                         shutdown_script, self.context.get_holder_selected_contest_delay(),
+                                                         &self.context.destination_script, (funding_txo, funding_txo_script.clone()),
+                                                         &self.context.channel_transaction_parameters,
+                                                         funding_redeemscript.clone(), self.context.channel_value_satoshis,
+                                                         obscure_factor,
+                                                         holder_commitment_tx, best_block, self.context.counterparty_node_id);
+
+               channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.context.cur_counterparty_commitment_transaction_number, self.context.counterparty_cur_commitment_point.unwrap(), logger);
+
+               self.context.channel_state = ChannelState::FundingSent as u32;
+               self.context.channel_id = funding_txo.to_channel_id();
+               self.context.cur_counterparty_commitment_transaction_number -= 1;
+               self.context.cur_holder_commitment_transaction_number -= 1;
+
+               log_info!(logger, "Generated funding_signed for peer for channel {}", log_bytes!(self.context.channel_id()));
+
+               // Promote the channel to a full-fledged one now that we have updated the state and have a
+               // `ChannelMonitor`.
+               let mut channel = Channel {
+                       context: self.context,
+               };
+               let channel_id = channel.context.channel_id.clone();
+               let need_channel_ready = channel.check_get_channel_ready(0).is_some();
+               channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
+
+               Ok((channel, msgs::FundingSigned {
+                       channel_id,
+                       signature,
+                       #[cfg(taproot)]
+                       partial_signature_with_nonce: None,
+               }, channel_monitor))
+       }
 }
 
 const SERIALIZATION_VERSION: u8 = 3;
@@ -7491,7 +7496,7 @@ mod tests {
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let (mut node_a_chan, funding_created_msg) = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
-               let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).unwrap();
+               let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
 
                // Node B --> Node A: funding signed
                let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -7617,7 +7622,7 @@ mod tests {
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let (mut node_a_chan, funding_created_msg) = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
-               let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).unwrap();
+               let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
 
                // Node B --> Node A: funding signed
                let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -7805,7 +7810,7 @@ mod tests {
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let (mut node_a_chan, funding_created_msg) = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
-               let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).unwrap();
+               let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
 
                // Node B --> Node A: funding signed
                let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
index 27014052b04c6de986c673322a085c5308a7397b..2dd091010c9edb85e96d482d9a162fd3eaacdfad 100644 (file)
@@ -2182,6 +2182,11 @@ where
                                                peer_state.latest_features.clone());
                                        res.push(details);
                                }
+                               for (_channel_id, channel) in peer_state.inbound_v1_channel_by_id.iter() {
+                                       let details = ChannelDetails::from_channel_context(&channel.context, best_block_height,
+                                               peer_state.latest_features.clone());
+                                       res.push(details);
+                               }
                                for (_channel_id, channel) in peer_state.outbound_v1_channel_by_id.iter() {
                                        let details = ChannelDetails::from_channel_context(&channel.context, best_block_height,
                                                peer_state.latest_features.clone());
@@ -2437,6 +2442,13 @@ where
                                self.finish_force_close_channel(chan.context.force_shutdown(false));
                                // Prefunded channel has no update
                                (None, chan.context.get_counterparty_node_id())
+                       } else if let hash_map::Entry::Occupied(chan) = peer_state.inbound_v1_channel_by_id.entry(channel_id.clone()) {
+                               log_error!(self.logger, "Force-closing channel {}", log_bytes!(channel_id[..]));
+                               self.issue_channel_close_events(&chan.get().context, closure_reason);
+                               let mut chan = remove_channel!(self, chan);
+                               self.finish_force_close_channel(chan.context.force_shutdown(false));
+                               // Prefunded channel has no update
+                               (None, chan.context.get_counterparty_node_id())
                        } else {
                                return Err(APIError::ChannelUnavailable{ err: format!("Channel with id {} not found for the passed counterparty node_id {}", log_bytes!(*channel_id), peer_node_id) });
                        }
@@ -4872,7 +4884,7 @@ where
                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                let is_only_peer_channel = peer_state.total_channel_count() == 1;
-               match peer_state.channel_by_id.entry(temporary_channel_id.clone()) {
+               match peer_state.inbound_v1_channel_by_id.entry(temporary_channel_id.clone()) {
                        hash_map::Entry::Occupied(mut channel) => {
                                if !channel.get().inbound_is_awaiting_accept() {
                                        return Err(APIError::APIMisuseError { err: "The channel isn't currently awaiting to be accepted.".to_owned() });
@@ -4946,12 +4958,19 @@ where
        ) -> usize {
                let mut num_unfunded_channels = 0;
                for (_, chan) in peer.channel_by_id.iter() {
+                       // This covers non-zero-conf inbound `Channel`s that we are currently monitoring, but those
+                       // which have not yet had any confirmations on-chain.
                        if !chan.context.is_outbound() && chan.context.minimum_depth().unwrap_or(1) != 0 &&
                                chan.context.get_funding_tx_confirmations(best_block_height) == 0
                        {
                                num_unfunded_channels += 1;
                        }
                }
+               for (_, chan) in peer.inbound_v1_channel_by_id.iter() {
+                       if chan.context.minimum_depth().unwrap_or(1) != 0 {
+                               num_unfunded_channels += 1;
+                       }
+               }
                num_unfunded_channels
        }
 
@@ -5037,7 +5056,7 @@ where
                                        channel_type: channel.context.get_channel_type().clone(),
                                }, None));
                        }
-                       peer_state.channel_by_id.insert(channel_id, channel);
+                       peer_state.inbound_v1_channel_by_id.insert(channel_id, channel);
                }
                Ok(())
        }
@@ -5083,12 +5102,24 @@ where
 
                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
-               let ((funding_msg, monitor), chan) =
-                       match peer_state.channel_by_id.entry(msg.temporary_channel_id) {
-                               hash_map::Entry::Occupied(mut chan) => {
-                                       (try_chan_entry!(self, chan.get_mut().funding_created(msg, best_block, &self.signer_provider, &self.logger), chan), chan.remove())
+               let (chan, funding_msg, monitor) =
+                       match peer_state.inbound_v1_channel_by_id.remove(&msg.temporary_channel_id) {
+                               Some(inbound_chan) => {
+                                       match inbound_chan.funding_created(msg, best_block, &self.signer_provider, &self.logger) {
+                                               Ok(res) => res,
+                                               Err((mut inbound_chan, err)) => {
+                                                       // We've already removed this inbound channel from the map in `PeerState`
+                                                       // above so at this point we just need to clean up any lingering entries
+                                                       // concerning this channel as it is safe to do so.
+                                                       update_maps_on_chan_removal!(self, &inbound_chan.context);
+                                                       let user_id = inbound_chan.context.get_user_id();
+                                                       let shutdown_res = inbound_chan.context.force_shutdown(false);
+                                                       return Err(MsgHandleErrInternal::from_finish_shutdown(format!("{}", err),
+                                                               msg.temporary_channel_id, user_id, shutdown_res, None));
+                                               },
+                                       }
                                },
-                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id))
+                               None => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id))
                        };
 
                match peer_state.channel_by_id.entry(funding_msg.channel_id) {
@@ -6896,6 +6927,11 @@ where
                                        }
                                        true
                                });
+                               peer_state.inbound_v1_channel_by_id.retain(|_, chan| {
+                                       update_maps_on_chan_removal!(self, &chan.context);
+                                       self.issue_channel_close_events(&chan.context, ClosureReason::DisconnectedPeer);
+                                       false
+                               });
                                peer_state.outbound_v1_channel_by_id.retain(|_, chan| {
                                        update_maps_on_chan_removal!(self, &chan.context);
                                        self.issue_channel_close_events(&chan.context, ClosureReason::DisconnectedPeer);
index 16d59a292b3e7f70777583d355d8492058e12f25..6107642cbf27c644bbe66691853adf3709d7fe8d 100644 (file)
@@ -794,6 +794,17 @@ macro_rules! get_outbound_v1_channel_ref {
        }
 }
 
+#[cfg(test)]
+macro_rules! get_inbound_v1_channel_ref {
+       ($node: expr, $counterparty_node: expr, $per_peer_state_lock: ident, $peer_state_lock: ident, $channel_id: expr) => {
+               {
+                       $per_peer_state_lock = $node.node.per_peer_state.read().unwrap();
+                       $peer_state_lock = $per_peer_state_lock.get(&$counterparty_node.node.get_our_node_id()).unwrap().lock().unwrap();
+                       $peer_state_lock.inbound_v1_channel_by_id.get_mut(&$channel_id).unwrap()
+               }
+       }
+}
+
 #[cfg(test)]
 macro_rules! get_feerate {
        ($node: expr, $counterparty_node: expr, $channel_id: expr) => {
index 92b66505cda172f6e91c065804510f254ee20dc1..b9468dc7821d8ac1abccedd28c249378e17087f9 100644 (file)
@@ -180,7 +180,7 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) {
                let mut sender_node_per_peer_lock;
                let mut sender_node_peer_state_lock;
                if send_from_initiator {
-                       let chan = get_channel_ref!(sender_node, counterparty_node, sender_node_per_peer_lock, sender_node_peer_state_lock, temp_channel_id);
+                       let chan = get_inbound_v1_channel_ref!(sender_node, counterparty_node, sender_node_per_peer_lock, sender_node_peer_state_lock, temp_channel_id);
                        chan.context.holder_selected_channel_reserve_satoshis = 0;
                        chan.context.holder_max_htlc_value_in_flight_msat = 100_000_000;
                } else {
@@ -7874,7 +7874,7 @@ fn test_reject_funding_before_inbound_channel_accepted() {
        let accept_chan_msg = {
                let mut node_1_per_peer_lock;
                let mut node_1_peer_state_lock;
-               let channel =  get_channel_ref!(&nodes[1], nodes[0], node_1_per_peer_lock, node_1_peer_state_lock, temp_channel_id);
+               let channel =  get_inbound_v1_channel_ref!(&nodes[1], nodes[0], node_1_per_peer_lock, node_1_peer_state_lock, temp_channel_id);
                channel.get_accept_channel_message()
        };
        nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_chan_msg);