- /// When a transaction is confirmed, we check whether it is or spends the funding transaction
- /// In the first case, we store the confirmation height and calculating the short channel id.
- /// In the second, we simply return an Err indicating we need to be force-closed now.
- pub fn transactions_confirmed<NS: Deref, L: Deref>(
- &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData,
- genesis_block_hash: BlockHash, node_signer: &NS, user_config: &UserConfig, logger: &L
- ) -> Result<(Option<msgs::ChannelReady>, Option<msgs::AnnouncementSignatures>), ClosureReason>
- where
- NS::Target: NodeSigner,
- L::Target: Logger
- {
- if let Some(funding_txo) = self.context.get_funding_txo() {
- for &(index_in_block, tx) in txdata.iter() {
- // Check if the transaction is the expected funding transaction, and if it is,
- // check that it pays the right amount to the right script.
- if self.context.funding_tx_confirmation_height == 0 {
- if tx.txid() == funding_txo.txid {
- let txo_idx = funding_txo.index as usize;
- if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() ||
- tx.output[txo_idx].value != self.context.channel_value_satoshis {
- if self.context.is_outbound() {
- // If we generated the funding transaction and it doesn't match what it
- // should, the client is really broken and we should just panic and
- // tell them off. That said, because hash collisions happen with high
- // probability in fuzzing mode, if we're fuzzing we just close the
- // channel and move on.
- #[cfg(not(fuzzing))]
- panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
- }
- self.context.update_time_counter += 1;
- let err_reason = "funding tx had wrong script/value or output index";
- return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
- } else {
- if self.context.is_outbound() {
- for input in tx.input.iter() {
- if input.witness.is_empty() {
- // We generated a malleable funding transaction, implying we've
- // just exposed ourselves to funds loss to our counterparty.
- #[cfg(not(fuzzing))]
- panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
- }
- }
- }
- self.context.funding_tx_confirmation_height = height;
- self.context.funding_tx_confirmed_in = Some(*block_hash);
- self.context.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) {
- Ok(scid) => Some(scid),
- Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"),
- }
- }
- }
- // If we allow 1-conf funding, we may need to check for channel_ready here and
- // send it immediately instead of waiting for a best_block_updated call (which
- // may have already happened for this block).
- if let Some(channel_ready) = self.check_get_channel_ready(height) {
- log_info!(logger, "Sending a channel_ready to our peer for channel {}", log_bytes!(self.context.channel_id));
- let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger);
- return Ok((Some(channel_ready), announcement_sigs));
- }
- }
- for inp in tx.input.iter() {
- if inp.previous_output == funding_txo.into_bitcoin_outpoint() {
- log_info!(logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(self.context.channel_id()));
- return Err(ClosureReason::CommitmentTxConfirmed);
- }
- }
- }
+ /// Updates channel state with knowledge of the funding transaction's txid/index, and generates
+ /// a funding_created message for the remote peer.
+ /// Panics if called at some time other than immediately after initial handshake, if called twice,
+ /// or if called on an inbound channel.
+ /// Note that channel_id changes during this call!
+ /// Do NOT broadcast the funding transaction until after a successful funding_signed call!
+ /// If an Err is returned, it is a ChannelError::Close.
+ pub fn get_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L)
+ -> Result<(Channel<Signer>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
+ if !self.context.is_outbound() {
+ panic!("Tried to create outbound funding_created message on an inbound channel!");
+ }
+ if self.context.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) {
+ panic!("Tried to get a funding_created messsage at a time other than immediately after initial handshake completion (or tried to get funding_created twice)");
+ }
+ 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");