X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=bac45076891aefc9ab2df35187e2847002e20c27;hb=11bdcdaa08e5e56fadc54857d49412341a528b76;hp=8d6144fc25f9c3ed4a123c77406cc43b6ca4924f;hpb=2d266794c2133782938ce62a96538ef138c85781;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 8d6144fc..bac45076 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -259,6 +259,11 @@ enum HTLCUpdateAwaitingACK { htlc_id: u64, err_packet: msgs::OnionErrorPacket, }, + FailMalformedHTLC { + htlc_id: u64, + failure_code: u16, + sha256_of_onion: [u8; 32], + }, } macro_rules! define_state_flags { @@ -793,7 +798,6 @@ pub(super) struct MonitorRestoreUpdates { pub(super) struct SignerResumeUpdates { pub commitment_update: Option, pub funding_signed: Option, - pub funding_created: Option, pub channel_ready: Option, } @@ -2407,38 +2411,6 @@ impl ChannelContext where SP::Target: SignerProvider { } } - /// Only allowed after [`Self::channel_transaction_parameters`] is set. - fn get_funding_created_msg(&mut self, logger: &L) -> Option where L::Target: Logger { - let counterparty_keys = self.build_remote_transaction_keys(); - let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx; - let signature = match &self.holder_signer { - // TODO (taproot|arik): move match into calling method for Taproot - ChannelSignerType::Ecdsa(ecdsa) => { - ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx) - .map(|(sig, _)| sig).ok()? - }, - // TODO (taproot|arik) - #[cfg(taproot)] - _ => todo!() - }; - - if self.signer_pending_funding { - log_trace!(logger, "Counterparty commitment signature ready for funding_created message: clearing signer_pending_funding"); - self.signer_pending_funding = false; - } - - Some(msgs::FundingCreated { - temporary_channel_id: self.temporary_channel_id.unwrap(), - funding_txid: self.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().txid, - funding_output_index: self.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().index, - signature, - #[cfg(taproot)] - partial_signature_with_nonce: None, - #[cfg(taproot)] - next_local_nonce: None, - }) - } - /// Only allowed after [`Self::channel_transaction_parameters`] is set. fn get_funding_signed_msg(&mut self, logger: &L) -> (CommitmentTransaction, Option) where L::Target: Logger { let counterparty_keys = self.build_remote_transaction_keys(); @@ -2551,6 +2523,64 @@ struct CommitmentTxInfoCached { feerate: u32, } +/// Contents of a wire message that fails an HTLC backwards. Useful for [`Channel::fail_htlc`] to +/// fail with either [`msgs::UpdateFailMalformedHTLC`] or [`msgs::UpdateFailHTLC`] as needed. +trait FailHTLCContents { + type Message: FailHTLCMessageName; + fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message; + fn to_inbound_htlc_state(self) -> InboundHTLCState; + fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK; +} +impl FailHTLCContents for msgs::OnionErrorPacket { + type Message = msgs::UpdateFailHTLC; + fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message { + msgs::UpdateFailHTLC { htlc_id, channel_id, reason: self } + } + fn to_inbound_htlc_state(self) -> InboundHTLCState { + InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(self)) + } + fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK { + HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self } + } +} +impl FailHTLCContents for (u16, [u8; 32]) { + type Message = msgs::UpdateFailMalformedHTLC; // (failure_code, sha256_of_onion) + fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message { + msgs::UpdateFailMalformedHTLC { + htlc_id, + channel_id, + failure_code: self.0, + sha256_of_onion: self.1 + } + } + fn to_inbound_htlc_state(self) -> InboundHTLCState { + InboundHTLCState::LocalRemoved( + InboundHTLCRemovalReason::FailMalformed((self.1, self.0)) + ) + } + fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK { + HTLCUpdateAwaitingACK::FailMalformedHTLC { + htlc_id, + failure_code: self.0, + sha256_of_onion: self.1 + } + } +} + +trait FailHTLCMessageName { + fn name() -> &'static str; +} +impl FailHTLCMessageName for msgs::UpdateFailHTLC { + fn name() -> &'static str { + "update_fail_htlc" + } +} +impl FailHTLCMessageName for msgs::UpdateFailMalformedHTLC { + fn name() -> &'static str { + "update_fail_malformed_htlc" + } +} + impl Channel where SP::Target: SignerProvider, ::EcdsaSigner: WriteableEcdsaChannelSigner @@ -2752,7 +2782,9 @@ impl Channel where return UpdateFulfillFetch::DuplicateClaim {}; } }, - &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { + &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } | + &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => + { if htlc_id_arg == htlc_id { log_warn!(logger, "Have preimage and want to fulfill HTLC with pending failure against channel {}", &self.context.channel_id()); // TODO: We may actually be able to switch to a fulfill here, though its @@ -2849,6 +2881,17 @@ impl Channel where .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) } + /// Used for failing back with [`msgs::UpdateFailMalformedHTLC`]. For now, this is used when we + /// want to fail blinded HTLCs where we are not the intro node. + /// + /// See [`Self::queue_fail_htlc`] for more info. + pub fn queue_fail_malformed_htlc( + &mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L + ) -> Result<(), ChannelError> where L::Target: Logger { + self.fail_htlc(htlc_id_arg, (failure_code, sha256_of_onion), true, logger) + .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) + } + /// We can only have one resolution per HTLC. In some cases around reconnect, we may fulfill /// an HTLC more than once or fulfill once and then attempt to fail after reconnect. We cannot, /// however, fail more than once as we wait for an upstream failure to be irrevocably committed @@ -2857,8 +2900,10 @@ impl Channel where /// If we do fail twice, we `debug_assert!(false)` and return `Ok(None)`. Thus, this will always /// return `Ok(_)` if preconditions are met. In any case, `Err`s will only be /// [`ChannelError::Ignore`]. - fn fail_htlc(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, mut force_holding_cell: bool, logger: &L) - -> Result, ChannelError> where L::Target: Logger { + fn fail_htlc( + &mut self, htlc_id_arg: u64, err_packet: E, mut force_holding_cell: bool, + logger: &L + ) -> Result, ChannelError> where L::Target: Logger { if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { panic!("Was asked to fail an HTLC when channel was not in an operational state"); } @@ -2911,7 +2956,9 @@ impl Channel where return Ok(None); } }, - &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { + &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } | + &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => + { if htlc_id_arg == htlc_id { debug_assert!(false, "Tried to fail an HTLC that was already failed"); return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned())); @@ -2921,120 +2968,21 @@ impl Channel where } } log_trace!(logger, "Placing failure for HTLC ID {} in holding cell in channel {}.", htlc_id_arg, &self.context.channel_id()); - self.context.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::FailHTLC { - htlc_id: htlc_id_arg, - err_packet, - }); + self.context.holding_cell_htlc_updates.push(err_packet.to_htlc_update_awaiting_ack(htlc_id_arg)); return Ok(None); } - log_trace!(logger, "Failing HTLC ID {} back with a update_fail_htlc message in channel {}.", htlc_id_arg, &self.context.channel_id()); + log_trace!(logger, "Failing HTLC ID {} back with {} message in channel {}.", htlc_id_arg, + E::Message::name(), &self.context.channel_id()); { let htlc = &mut self.context.pending_inbound_htlcs[pending_idx]; - htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(err_packet.clone())); + htlc.state = err_packet.clone().to_inbound_htlc_state(); } - Ok(Some(msgs::UpdateFailHTLC { - channel_id: self.context.channel_id(), - htlc_id: htlc_id_arg, - reason: err_packet - })) + Ok(Some(err_packet.to_message(htlc_id_arg, self.context.channel_id()))) } // Message handlers: - - /// 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( - &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result::EcdsaSigner>, ChannelError> - where - L::Target: Logger - { - if !self.context.is_outbound() { - return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned())); - } - if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) { - return Err(ChannelError::Close("Received funding_signed in strange state!".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_script = self.context.get_funding_redeemscript(); - - 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 {}", - &self.context.channel_id(), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); - - let holder_signer = 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, &holder_signer, 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 our commitment transaction, allowing us to broadcast the tx if we wish. - if let Err(_) = self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.context.get_counterparty_pubkeys().funding_pubkey) { - return Err(ChannelError::Close("Invalid funding_signed signature from peer".to_owned())); - } - } - - 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.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()) - .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?; - - - let funding_redeemscript = self.context.get_funding_redeemscript(); - let funding_txo = self.context.get_funding_txo().unwrap(); - 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), - &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_initial_counterparty_commitment_tx( - counterparty_initial_bitcoin_tx.txid, Vec::new(), - self.context.cur_counterparty_commitment_transaction_number, - self.context.counterparty_cur_commitment_point.unwrap(), - counterparty_initial_commitment_tx.feerate_per_kw(), - counterparty_initial_commitment_tx.to_broadcaster_value_sat(), - counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); - - assert!(!self.context.channel_state.is_monitor_update_in_progress()); // We have no had any monitor(s) yet to fail update! - if self.context.is_batch_funding() { - self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); - } else { - self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); - } - self.context.cur_holder_commitment_transaction_number -= 1; - self.context.cur_counterparty_commitment_transaction_number -= 1; - - log_info!(logger, "Received funding_signed from peer for channel {}", &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(channel_monitor) - } - /// Updates the state of the channel to indicate that all channels in the batch have received /// funding_signed and persisted their monitors. /// The funding transaction is consequently allowed to be broadcast, and the channel can be @@ -3689,6 +3637,20 @@ impl Channel where } } }, + &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => { + match self.fail_htlc(htlc_id, (failure_code, sha256_of_onion), false, logger) { + Ok(update_fail_malformed_opt) => { + debug_assert!(update_fail_malformed_opt.is_some()); // See above comment + update_fail_count += 1; + }, + Err(e) => { + if let ChannelError::Ignore(_) = e {} + else { + panic!("Got a non-IgnoreError action trying to fail holding cell HTLC"); + } + } + } + }, } } if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() { @@ -4308,20 +4270,15 @@ impl Channel where let channel_ready = if funding_signed.is_some() { self.check_get_channel_ready(0) } else { None }; - let funding_created = if self.context.signer_pending_funding && self.context.is_outbound() { - self.context.get_funding_created_msg(logger) - } else { None }; - log_trace!(logger, "Signer unblocked with {} commitment_update, {} funding_signed, {} funding_created, and {} channel_ready", + log_trace!(logger, "Signer unblocked with {} commitment_update, {} funding_signed and {} channel_ready", if commitment_update.is_some() { "a" } else { "no" }, if funding_signed.is_some() { "a" } else { "no" }, - if funding_created.is_some() { "a" } else { "no" }, if channel_ready.is_some() { "a" } else { "no" }); SignerResumeUpdates { commitment_update, funding_signed, - funding_created, channel_ready, } } @@ -6103,12 +6060,9 @@ impl Channel where /// Begins the shutdown process, getting a message for the remote peer and returning all /// holding cell HTLCs for payment failure. - /// - /// May jump to the channel being fully shutdown (see [`Self::is_shutdown`]) in which case no - /// [`ChannelMonitorUpdate`] will be returned). pub fn get_shutdown(&mut self, signer_provider: &SP, their_features: &InitFeatures, target_feerate_sats_per_kw: Option, override_shutdown_script: Option) - -> Result<(msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>, Option), APIError> + -> Result<(msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>), APIError> { for htlc in self.context.pending_outbound_htlcs.iter() { if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { @@ -6129,16 +6083,9 @@ impl Channel where return Err(APIError::ChannelUnavailable{err: "Cannot begin shutdown while peer is disconnected or we're waiting on a monitor update, maybe force-close instead?".to_owned()}); } - // If we haven't funded the channel yet, we don't need to bother ensuring the shutdown - // script is set, we just force-close and call it a day. - let mut chan_closed = false; - if self.context.channel_state.is_pre_funded_state() { - chan_closed = true; - } - let update_shutdown_script = match self.context.shutdown_scriptpubkey { Some(_) => false, - None if !chan_closed => { + None => { // use override shutdown script if provided let shutdown_scriptpubkey = match override_shutdown_script { Some(script) => script, @@ -6156,25 +6103,11 @@ impl Channel where self.context.shutdown_scriptpubkey = Some(shutdown_scriptpubkey); true }, - None => false, }; // From here on out, we may not fail! self.context.target_closing_feerate_sats_per_kw = target_feerate_sats_per_kw; - let shutdown_result = if self.context.channel_state.is_pre_funded_state() { - let shutdown_result = ShutdownResult { - monitor_update: None, - dropped_outbound_htlcs: Vec::new(), - unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(), - channel_id: self.context.channel_id, - counterparty_node_id: self.context.counterparty_node_id, - }; - self.context.channel_state = ChannelState::ShutdownComplete; - Some(shutdown_result) - } else { - self.context.channel_state.set_local_shutdown_sent(); - None - }; + self.context.channel_state.set_local_shutdown_sent(); self.context.update_time_counter += 1; let monitor_update = if update_shutdown_script { @@ -6210,7 +6143,7 @@ impl Channel where debug_assert!(!self.is_shutdown() || monitor_update.is_none(), "we can't both complete shutdown and return a monitor update"); - Ok((shutdown, monitor_update, dropped_outbound_htlcs, shutdown_result)) + Ok((shutdown, monitor_update, dropped_outbound_htlcs)) } pub fn inflight_htlc_sources(&self) -> impl Iterator { @@ -6438,6 +6371,38 @@ impl OutboundV1Channel where SP::Target: SignerProvider { }) } + /// Only allowed after [`ChannelContext::channel_transaction_parameters`] is set. + fn get_funding_created_msg(&mut self, logger: &L) -> Option where L::Target: Logger { + 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 signature = match &self.context.holder_signer { + // TODO (taproot|arik): move match into calling method for Taproot + ChannelSignerType::Ecdsa(ecdsa) => { + ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.context.secp_ctx) + .map(|(sig, _)| sig).ok()? + }, + // TODO (taproot|arik) + #[cfg(taproot)] + _ => todo!() + }; + + if self.context.signer_pending_funding { + log_trace!(logger, "Counterparty commitment signature ready for funding_created message: clearing signer_pending_funding"); + self.context.signer_pending_funding = false; + } + + Some(msgs::FundingCreated { + temporary_channel_id: self.context.temporary_channel_id.unwrap(), + funding_txid: self.context.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().txid, + funding_output_index: self.context.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().index, + signature, + #[cfg(taproot)] + partial_signature_with_nonce: None, + #[cfg(taproot)] + next_local_nonce: None, + }) + } + /// 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, @@ -6445,8 +6410,8 @@ impl OutboundV1Channel where SP::Target: SignerProvider { /// 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(mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, logger: &L) - -> Result<(Channel, Option), (Self, ChannelError)> where L::Target: Logger { + pub fn get_funding_created(&mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, logger: &L) + -> Result, (Self, ChannelError)> where L::Target: Logger { if !self.context.is_outbound() { panic!("Tried to create outbound funding_created message on an inbound channel!"); } @@ -6481,7 +6446,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { self.context.funding_transaction = Some(funding_transaction); self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding); - let funding_created = self.context.get_funding_created_msg(logger); + let funding_created = self.get_funding_created_msg(logger); if funding_created.is_none() { if !self.context.signer_pending_funding { log_trace!(logger, "funding_created awaiting signer; setting signer_pending_funding"); @@ -6489,11 +6454,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { } } - let channel = Channel { - context: self.context, - }; - - Ok((channel, funding_created)) + Ok(funding_created) } fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures { @@ -6736,6 +6697,112 @@ impl OutboundV1Channel where SP::Target: SignerProvider { Ok(()) } + + /// 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( + mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L + ) -> Result<(Channel, ChannelMonitor<::EcdsaSigner>), (OutboundV1Channel, ChannelError)> + where + L::Target: Logger + { + if !self.context.is_outbound() { + return Err((self, ChannelError::Close("Received funding_signed for an inbound channel?".to_owned()))); + } + if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) { + return Err((self, ChannelError::Close("Received funding_signed in strange state!".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_script = self.context.get_funding_redeemscript(); + + 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 {}", + &self.context.channel_id(), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); + + let holder_signer = 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, &holder_signer, 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 our commitment transaction, allowing us to broadcast the tx if we wish. + if let Err(_) = self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.context.get_counterparty_pubkeys().funding_pubkey) { + return Err((self, ChannelError::Close("Invalid funding_signed signature from peer".to_owned()))); + } + } + + 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() + ); + + let validated = + self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()); + if validated.is_err() { + return Err((self, ChannelError::Close("Failed to validate our commitment".to_owned()))); + } + + let funding_redeemscript = self.context.get_funding_redeemscript(); + let funding_txo = self.context.get_funding_txo().unwrap(); + 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), + &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_initial_counterparty_commitment_tx( + counterparty_initial_bitcoin_tx.txid, Vec::new(), + self.context.cur_counterparty_commitment_transaction_number, + self.context.counterparty_cur_commitment_point.unwrap(), + counterparty_initial_commitment_tx.feerate_per_kw(), + counterparty_initial_commitment_tx.to_broadcaster_value_sat(), + counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); + + assert!(!self.context.channel_state.is_monitor_update_in_progress()); // We have no had any monitor(s) yet to fail update! + if self.context.is_batch_funding() { + self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); + } else { + self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); + } + self.context.cur_holder_commitment_transaction_number -= 1; + self.context.cur_counterparty_commitment_transaction_number -= 1; + + log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id()); + + let mut channel = Channel { context: self.context }; + + 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, channel_monitor)) + } + + /// Indicates that the signer may have some signatures for us, so we should retry if we're + /// blocked. + #[allow(unused)] + pub fn signer_maybe_unblocked(&mut self, logger: &L) -> Option where L::Target: Logger { + if self.context.signer_pending_funding && self.context.is_outbound() { + log_trace!(logger, "Signer unblocked a funding_created"); + self.get_funding_created_msg(logger) + } else { None } + } } /// A not-yet-funded inbound (from counterparty) channel using V1 channel establishment. @@ -7454,6 +7521,8 @@ impl Writeable for Channel where SP::Target: SignerProvider { let mut holding_cell_skimmed_fees: Vec> = Vec::new(); let mut holding_cell_blinding_points: Vec> = Vec::new(); + // Vec of (htlc_id, failure_code, sha256_of_onion) + let mut malformed_htlcs: Vec<(u64, u16, [u8; 32])> = Vec::new(); (self.context.holding_cell_htlc_updates.len() as u64).write(writer)?; for update in self.context.holding_cell_htlc_updates.iter() { match update { @@ -7481,6 +7550,18 @@ impl Writeable for Channel where SP::Target: SignerProvider { htlc_id.write(writer)?; err_packet.write(writer)?; } + &HTLCUpdateAwaitingACK::FailMalformedHTLC { + htlc_id, failure_code, sha256_of_onion + } => { + // We don't want to break downgrading by adding a new variant, so write a dummy + // `::FailHTLC` variant and write the real malformed error as an optional TLV. + malformed_htlcs.push((htlc_id, failure_code, sha256_of_onion)); + + let dummy_err_packet = msgs::OnionErrorPacket { data: Vec::new() }; + 2u8.write(writer)?; + htlc_id.write(writer)?; + dummy_err_packet.write(writer)?; + } } } @@ -7641,6 +7722,7 @@ impl Writeable for Channel where SP::Target: SignerProvider { (38, self.context.is_batch_funding, option), (39, pending_outbound_blinding_points, optional_vec), (41, holding_cell_blinding_points, optional_vec), + (43, malformed_htlcs, optional_vec), // Added in 0.0.119 }); Ok(()) @@ -7931,6 +8013,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut pending_outbound_blinding_points_opt: Option>> = None; let mut holding_cell_blinding_points_opt: Option>> = None; + let mut malformed_htlcs: Option> = None; + read_tlv_fields!(reader, { (0, announcement_sigs, option), (1, minimum_depth, option), @@ -7959,6 +8043,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch (38, is_batch_funding, option), (39, pending_outbound_blinding_points_opt, optional_vec), (41, holding_cell_blinding_points_opt, optional_vec), + (43, malformed_htlcs, optional_vec), // Added in 0.0.119 }); let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id { @@ -8053,6 +8138,22 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch if iter.next().is_some() { return Err(DecodeError::InvalidValue) } } + if let Some(malformed_htlcs) = malformed_htlcs { + for (malformed_htlc_id, failure_code, sha256_of_onion) in malformed_htlcs { + let htlc_idx = holding_cell_htlc_updates.iter().position(|htlc| { + if let HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet } = htlc { + let matches = *htlc_id == malformed_htlc_id; + if matches { debug_assert!(err_packet.data.is_empty()) } + matches + } else { false } + }).ok_or(DecodeError::InvalidValue)?; + let malformed_htlc = HTLCUpdateAwaitingACK::FailMalformedHTLC { + htlc_id: malformed_htlc_id, failure_code, sha256_of_onion + }; + let _ = core::mem::replace(&mut holding_cell_htlc_updates[htlc_idx], malformed_htlc); + } + } + Ok(Channel { context: ChannelContext { user_id, @@ -8364,11 +8465,12 @@ mod tests { value: 10000000, script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; - let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); + let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap(); // Node B --> Node A: funding signed - let _ = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger).unwrap(); + let res = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger); + let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; // Put some inbound and outbound HTLCs in A's channel. let htlc_amount_msat = 11_092_000; // put an amount below A's effective dust limit but above B's. @@ -8492,11 +8594,12 @@ mod tests { value: 10000000, script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; - let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); + let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap(); // Node B --> Node A: funding signed - let _ = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger).unwrap(); + let res = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger); + let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; // Now disconnect the two nodes and check that the commitment point in // Node B's channel_reestablish message is sane. @@ -8680,11 +8783,12 @@ mod tests { value: 10000000, script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; - let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); + let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap(); // Node B --> Node A: funding signed - let _ = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger).unwrap(); + let res = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger); + let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; // Make sure that receiving a channel update will update the Channel as expected. let update = ChannelUpdate { @@ -9850,11 +9954,8 @@ mod tests { }, ]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; - let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created( - tx.clone(), - funding_outpoint, - true, - &&logger, + let funding_created_msg = node_a_chan.get_funding_created( + tx.clone(), funding_outpoint, true, &&logger, ).map_err(|_| ()).unwrap(); let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created( &funding_created_msg.unwrap(), @@ -9872,12 +9973,10 @@ mod tests { // Receive funding_signed, but the channel will be configured to hold sending channel_ready and // broadcasting the funding transaction until the batch is ready. - let _ = node_a_chan.funding_signed( - &funding_signed_msg.unwrap(), - best_block, - &&keys_provider, - &&logger, - ).unwrap(); + let res = node_a_chan.funding_signed( + &funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger, + ); + let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; let node_a_updates = node_a_chan.monitor_updating_restored( &&logger, &&keys_provider,