X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=36c14242d9edffab80f07c864b0a35f5b8693fa5;hb=4c8dc2c2a0b9589298d937bf16061ae0ac99b31e;hp=990621c221adaabda96f481e4c5005310070e034;hpb=67736b7480051e624a8c69bf61d15f22beecd38f;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 990621c2..36c14242 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -24,7 +24,7 @@ use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; -use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{BlockHash, Txid}; @@ -51,7 +51,7 @@ use ln::onion_utils; use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT, OptionalField}; use ln::wire::Encode; use chain::keysinterface::{Sign, KeysInterface, KeysManager, InMemorySigner, Recipient}; -use util::config::UserConfig; +use util::config::{UserConfig, ChannelConfig}; use util::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason}; use util::{byte_utils, events}; use util::scid_utils::fake_scid; @@ -369,15 +369,6 @@ impl MsgHandleErrInternal { }, }, }, - ChannelError::CloseDelayBroadcast(msg) => LightningError { - err: msg.clone(), - action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { - channel_id, - data: msg - }, - }, - }, }, chan_id: None, shutdown_finish: None, @@ -870,7 +861,13 @@ pub(crate) const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 2 * 6 * 24 * 7; // the HTLC via a full update_fail_htlc/commitment_signed dance before we hit the // CLTV_CLAIM_BUFFER point (we static assert that it's at least 3 blocks more). pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6*7; -pub(super) const CLTV_FAR_FAR_AWAY: u32 = 6 * 24 * 7; //TODO? +// This should be long enough to allow a payment path drawn across multiple routing hops with substantial +// `cltv_expiry_delta`. Indeed, the length of those values is the reaction delay offered to a routing node +// in case of HTLC on-chain settlement. While appearing less competitive, a node operator could decide to +// scale them up to suit its security policy. At the network-level, we shouldn't constrain them too much, +// while avoiding to introduce a DoS vector. Further, a low CTLV_FAR_FAR_AWAY could be a source of +// routing failure for any HTLC sender picking up an LDK node among the first hops. +pub(super) const CLTV_FAR_FAR_AWAY: u32 = 14 * 24 * 6; /// Minimum CLTV difference between the current block height and received inbound payments. /// Invoices generated for payment to us must set their `min_final_cltv_expiry` field to at least @@ -1095,6 +1092,10 @@ pub struct ChannelDetails { pub inbound_htlc_minimum_msat: Option, /// The largest value HTLC (in msat) we currently will accept, for this channel. pub inbound_htlc_maximum_msat: Option, + /// Set of configurable parameters that affect channel operation. + /// + /// This field is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.109. + pub config: Option, } impl ChannelDetails { @@ -1263,13 +1264,6 @@ macro_rules! convert_chan_err { (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, $channel.get_user_id(), shutdown_res, $self.get_channel_update_for_broadcast(&$channel).ok())) }, - ChannelError::CloseDelayBroadcast(msg) => { - log_error!($self.logger, "Channel {} need to be shutdown but closing transactions not broadcast due to {}", log_bytes!($channel_id[..]), msg); - update_maps_on_chan_removal!($self, $short_to_id, $channel); - let shutdown_res = $channel.force_shutdown(false); - (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, $channel.get_user_id(), - shutdown_res, $self.get_channel_update_for_broadcast(&$channel).ok())) - } } } } @@ -1759,7 +1753,8 @@ impl ChannelMana is_usable: channel.is_live(), is_public: channel.should_announce(), inbound_htlc_minimum_msat: Some(channel.get_holder_htlc_minimum_msat()), - inbound_htlc_maximum_msat: channel.get_holder_htlc_maximum_msat() + inbound_htlc_maximum_msat: channel.get_holder_htlc_maximum_msat(), + config: Some(channel.config()), }); } } @@ -1934,7 +1929,8 @@ impl ChannelMana /// `peer_msg` should be set when we receive a message from a peer, but not set when the /// user closes, which will be re-exposed as the `ChannelClosed` reason. - fn force_close_channel_with_peer(&self, channel_id: &[u8; 32], peer_node_id: &PublicKey, peer_msg: Option<&String>) -> Result { + fn force_close_channel_with_peer(&self, channel_id: &[u8; 32], peer_node_id: &PublicKey, peer_msg: Option<&String>, broadcast: bool) + -> Result { let mut chan = { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; @@ -1953,7 +1949,7 @@ impl ChannelMana } }; log_error!(self.logger, "Force-closing channel {}", log_bytes!(channel_id[..])); - self.finish_force_close_channel(chan.force_shutdown(true)); + self.finish_force_close_channel(chan.force_shutdown(broadcast)); if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { let mut channel_state = self.channel_state.lock().unwrap(); channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { @@ -1964,13 +1960,9 @@ impl ChannelMana Ok(chan.get_counterparty_node_id()) } - /// Force closes a channel, immediately broadcasting the latest local commitment transaction to - /// the chain and rejecting new HTLCs on the given channel. Fails if `channel_id` is unknown to - /// the manager, or if the `counterparty_node_id` isn't the counterparty of the corresponding - /// channel. - pub fn force_close_channel(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey) -> Result<(), APIError> { + fn force_close_sending_error(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey, broadcast: bool) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - match self.force_close_channel_with_peer(channel_id, counterparty_node_id, None) { + match self.force_close_channel_with_peer(channel_id, counterparty_node_id, None, broadcast) { Ok(counterparty_node_id) => { self.channel_state.lock().unwrap().pending_msg_events.push( events::MessageSendEvent::HandleError { @@ -1986,11 +1978,39 @@ impl ChannelMana } } + /// Force closes a channel, immediately broadcasting the latest local transaction(s) and + /// rejecting new HTLCs on the given channel. Fails if `channel_id` is unknown to + /// the manager, or if the `counterparty_node_id` isn't the counterparty of the corresponding + /// channel. + pub fn force_close_broadcasting_latest_txn(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey) + -> Result<(), APIError> { + self.force_close_sending_error(channel_id, counterparty_node_id, true) + } + + /// Force closes a channel, rejecting new HTLCs on the given channel but skips broadcasting + /// the latest local transaction(s). Fails if `channel_id` is unknown to the manager, or if the + /// `counterparty_node_id` isn't the counterparty of the corresponding channel. + /// + /// You can always get the latest local transaction(s) to broadcast from + /// [`ChannelMonitor::get_latest_holder_commitment_txn`]. + pub fn force_close_without_broadcasting_txn(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey) + -> Result<(), APIError> { + self.force_close_sending_error(channel_id, counterparty_node_id, false) + } + /// Force close all channels, immediately broadcasting the latest local commitment transaction /// for each to the chain and rejecting new HTLCs on each. - pub fn force_close_all_channels(&self) { + pub fn force_close_all_channels_broadcasting_latest_txn(&self) { + for chan in self.list_channels() { + let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id); + } + } + + /// Force close all channels rejecting new HTLCs on each but without broadcasting the latest + /// local transaction(s). + pub fn force_close_all_channels_without_broadcasting_txn(&self) { for chan in self.list_channels() { - let _ = self.force_close_channel(&chan.channel_id, &chan.counterparty.node_id); + let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id); } } @@ -2164,22 +2184,10 @@ impl ChannelMana } }, onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => { - let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap(); - - let blinding_factor = { - let mut sha = Sha256::engine(); - sha.input(&new_pubkey.serialize()[..]); - sha.input(&shared_secret); - Sha256::from_engine(sha).into_inner() - }; - - let public_key = if let Err(e) = new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor[..]) { - Err(e) - } else { Ok(new_pubkey) }; - + let new_pubkey = msg.onion_routing_packet.public_key.unwrap(); let outgoing_packet = msgs::OnionPacket { version: 0, - public_key, + public_key: onion_utils::next_hop_packet_pubkey(&self.secp_ctx, new_pubkey, &shared_secret), hop_data: new_packet_bytes, hmac: next_hop_hmac.clone(), }; @@ -2225,7 +2233,7 @@ impl ChannelMana }, Some(id) => Some(id.clone()), }; - let (chan_update_opt, forwardee_cltv_expiry_delta) = if let Some(forwarding_id) = forwarding_id_opt { + let chan_update_opt = if let Some(forwarding_id) = forwarding_id_opt { let chan = channel_state.as_mut().unwrap().by_id.get_mut(&forwarding_id).unwrap(); if !chan.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels { // Note that the behavior here should be identical to the above block - we @@ -2252,18 +2260,20 @@ impl ChannelMana if *amt_to_forward < chan.get_counterparty_htlc_minimum_msat() { // amount_below_minimum break Some(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt)); } - let fee = amt_to_forward.checked_mul(chan.get_fee_proportional_millionths() as u64) - .and_then(|prop_fee| { (prop_fee / 1000000) - .checked_add(chan.get_outbound_forwarding_fee_base_msat() as u64) }); - if fee.is_none() || msg.amount_msat < fee.unwrap() || (msg.amount_msat - fee.unwrap()) < *amt_to_forward { // fee_insufficient - break Some(("Prior hop has deviated from specified fees parameters or origin node has obsolete ones", 0x1000 | 12, chan_update_opt)); + if let Err((err, code)) = chan.htlc_satisfies_config(&msg, *amt_to_forward, *outgoing_cltv_value) { + break Some((err, code, chan_update_opt)); } - (chan_update_opt, chan.get_cltv_expiry_delta()) - } else { (None, MIN_CLTV_EXPIRY_DELTA) }; + chan_update_opt + } else { + if (msg.cltv_expiry as u64) < (*outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 { // incorrect_cltv_expiry + break Some(( + "Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", + 0x1000 | 13, None, + )); + } + None + }; - if (msg.cltv_expiry as u64) < (*outgoing_cltv_value) as u64 + forwardee_cltv_expiry_delta as u64 { // incorrect_cltv_expiry - break Some(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", 0x1000 | 13, chan_update_opt)); - } let cur_height = self.best_block.read().unwrap().height() + 1; // Theoretically, channel counterparty shouldn't send us a HTLC expiring now, // but we want to be robust wrt to counterparty packet sanitization (see @@ -2529,12 +2539,6 @@ impl ChannelMana if route.paths.len() < 1 { return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"})); } - if route.paths.len() > 10 { - // This limit is completely arbitrary - there aren't any real fundamental path-count - // limits. After we support retrying individual paths we should likely bump this, but - // for now more than 10 paths likely carries too much one-path failure. - return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "Sending over more than 10 paths is not currently supported"})); - } if payment_secret.is_none() && route.paths.len() > 1 { return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError{err: "Payment secret is required for multi-path payments".to_string()})); } @@ -2783,6 +2787,9 @@ impl ChannelMana /// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs /// or if no output was found which matches the parameters in [`Event::FundingGenerationReady`]. /// + /// Returns [`APIError::APIMisuseError`] if the funding transaction is not final for propagation + /// across the p2p network. + /// /// Returns [`APIError::ChannelUnavailable`] if a funding transaction has already been provided /// for the channel or if the channel has been closed as indicated by [`Event::ChannelClosed`]. /// @@ -2798,6 +2805,11 @@ impl ChannelMana /// not currently support replacing a funding transaction on an existing channel. Instead, /// create a new channel with a conflicting funding transaction. /// + /// Note to keep the miner incentives aligned in moving the blockchain forward, we recommend + /// the wallet software generating the funding transaction to apply anti-fee sniping as + /// implemented by Bitcoin Core wallet. See + /// for more details. + /// /// [`Event::FundingGenerationReady`]: crate::util::events::Event::FundingGenerationReady /// [`Event::ChannelClosed`]: crate::util::events::Event::ChannelClosed pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, funding_transaction: Transaction) -> Result<(), APIError> { @@ -2810,6 +2822,18 @@ impl ChannelMana }); } } + { + let height = self.best_block.read().unwrap().height(); + // Transactions are evaluated as final by network mempools at the next block. However, the modules + // constituting our Lightning node might not have perfect sync about their blockchain views. Thus, if + // the wallet module is in advance on the LDK view, allow one more block of headroom. + // TODO: updated if/when https://github.com/rust-bitcoin/rust-bitcoin/pull/994 landed and rust-bitcoin bumped. + if !funding_transaction.input.iter().all(|input| input.sequence == 0xffffffff) && funding_transaction.lock_time < 500_000_000 && funding_transaction.lock_time > height + 2 { + return Err(APIError::APIMisuseError { + err: "Funding transaction absolute timelock is non-final".to_owned() + }); + } + } self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, |chan, tx| { let mut output_index = None; let expected_spk = chan.get_funding_redeemscript().to_v0_p2wsh(); @@ -2839,15 +2863,15 @@ impl ChannelMana #[allow(dead_code)] // Messages of up to 64KB should never end up more than half full with addresses, as that would - // be absurd. We ensure this by checking that at least 500 (our stated public contract on when + // be absurd. We ensure this by checking that at least 100 (our stated public contract on when // broadcast_node_announcement panics) of the maximum-length addresses would fit in a 64KB // message... const HALF_MESSAGE_IS_ADDRS: u32 = ::core::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2; #[deny(const_err)] #[allow(dead_code)] // ...by failing to compile if the number of addresses that would be half of a message is - // smaller than 500: - const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; + // smaller than 100: + const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 100; /// Regenerates channel_announcements and generates a signed node_announcement from the given /// arguments, providing them in corresponding events via @@ -2864,13 +2888,13 @@ impl ChannelMana /// tying these addresses together and to this node. If you wish to preserve user privacy, /// addresses should likely contain only Tor Onion addresses. /// - /// Panics if `addresses` is absurdly large (more than 500). + /// Panics if `addresses` is absurdly large (more than 100). /// /// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - if addresses.len() > 500 { + if addresses.len() > 100 { panic!("More than half the message size was taken up by public addresses!"); } @@ -2920,6 +2944,73 @@ impl ChannelMana } } + /// Atomically updates the [`ChannelConfig`] for the given channels. + /// + /// Once the updates are applied, each eligible channel (advertised with a known short channel + /// ID and a change in [`forwarding_fee_proportional_millionths`], [`forwarding_fee_base_msat`], + /// or [`cltv_expiry_delta`]) has a [`BroadcastChannelUpdate`] event message generated + /// containing the new [`ChannelUpdate`] message which should be broadcast to the network. + /// + /// Returns [`ChannelUnavailable`] when a channel is not found or an incorrect + /// `counterparty_node_id` is provided. + /// + /// Returns [`APIMisuseError`] when a [`cltv_expiry_delta`] update is to be applied with a value + /// below [`MIN_CLTV_EXPIRY_DELTA`]. + /// + /// If an error is returned, none of the updates should be considered applied. + /// + /// [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths + /// [`forwarding_fee_base_msat`]: ChannelConfig::forwarding_fee_base_msat + /// [`cltv_expiry_delta`]: ChannelConfig::cltv_expiry_delta + /// [`BroadcastChannelUpdate`]: events::MessageSendEvent::BroadcastChannelUpdate + /// [`ChannelUpdate`]: msgs::ChannelUpdate + /// [`ChannelUnavailable`]: APIError::ChannelUnavailable + /// [`APIMisuseError`]: APIError::APIMisuseError + pub fn update_channel_config( + &self, counterparty_node_id: &PublicKey, channel_ids: &[[u8; 32]], config: &ChannelConfig, + ) -> Result<(), APIError> { + if config.cltv_expiry_delta < MIN_CLTV_EXPIRY_DELTA { + return Err(APIError::APIMisuseError { + err: format!("The chosen CLTV expiry delta is below the minimum of {}", MIN_CLTV_EXPIRY_DELTA), + }); + } + + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop( + &self.total_consistency_lock, &self.persistence_notifier, + ); + { + let mut channel_state_lock = self.channel_state.lock().unwrap(); + let channel_state = &mut *channel_state_lock; + for channel_id in channel_ids { + let channel_counterparty_node_id = channel_state.by_id.get(channel_id) + .ok_or(APIError::ChannelUnavailable { + err: format!("Channel with ID {} was not found", log_bytes!(*channel_id)), + })? + .get_counterparty_node_id(); + if channel_counterparty_node_id != *counterparty_node_id { + return Err(APIError::APIMisuseError { + err: "counterparty node id mismatch".to_owned(), + }); + } + } + for channel_id in channel_ids { + let channel = channel_state.by_id.get_mut(channel_id).unwrap(); + if !channel.update_config(config) { + continue; + } + if let Ok(msg) = self.get_channel_update_for_broadcast(channel) { + channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { msg }); + } else if let Ok(msg) = self.get_channel_update_for_unicast(channel) { + channel_state.pending_msg_events.push(events::MessageSendEvent::SendChannelUpdate { + node_id: channel.get_counterparty_node_id(), + msg, + }); + } + } + } + Ok(()) + } + /// Processes HTLCs which are pending waiting on random forward delay. /// /// Should only really ever be called in response to a PendingHTLCsForwardable event. @@ -3106,7 +3197,6 @@ impl ChannelMana // ChannelClosed event is generated by handle_error for us. Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel.channel_id(), channel.get_user_id(), channel.force_shutdown(true), self.get_channel_update_for_broadcast(&channel).ok())) }, - ChannelError::CloseDelayBroadcast(_) => { panic!("Wait is only generated on receipt of channel_reestablish, which is handled by try_chan_entry, we don't bother to support it here"); } }; handle_errors.push((counterparty_node_id, err)); continue; @@ -3445,6 +3535,8 @@ impl ChannelMana /// * Broadcasting `ChannelUpdate` messages if we've been disconnected from our peer for more /// than a minute, informing the network that they should no longer attempt to route over /// the channel. + /// * Expiring a channel's previous `ChannelConfig` if necessary to only allow forwarding HTLCs + /// with the current `ChannelConfig`. /// /// Note that this may cause reentrancy through `chain::Watch::update_channel` calls or feerate /// estimate fetches. @@ -3503,6 +3595,8 @@ impl ChannelMana _ => {}, } + chan.maybe_expire_prev_config(); + true }); @@ -3620,7 +3714,10 @@ impl ChannelMana // Fail a list of HTLCs that were just freed from the holding cell. The HTLCs need to be // failed backwards or, if they were one of our outgoing HTLCs, then their failure needs to // be surfaced to the user. - fn fail_holding_cell_htlcs(&self, mut htlcs_to_fail: Vec<(HTLCSource, PaymentHash)>, channel_id: [u8; 32]) { + fn fail_holding_cell_htlcs( + &self, mut htlcs_to_fail: Vec<(HTLCSource, PaymentHash)>, channel_id: [u8; 32], + _counterparty_node_id: &PublicKey + ) { for (htlc_src, payment_hash) in htlcs_to_fail.drain(..) { match htlc_src { HTLCSource::PreviousHopData(HTLCPreviousHopData { .. }) => { @@ -4349,7 +4446,7 @@ impl ChannelMana if chan.get().get_counterparty_node_id() != *counterparty_node_id { return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.temporary_channel_id)); } - try_chan_entry!(self, chan.get_mut().accept_channel(&msg, &self.default_configuration.peer_channel_config_limits, &their_features), channel_state, chan); + try_chan_entry!(self, chan.get_mut().accept_channel(&msg, &self.default_configuration.channel_handshake_limits, &their_features), channel_state, chan); (chan.get().get_value_satoshis(), chan.get().get_funding_redeemscript().to_v0_p2wsh(), chan.get().get_user_id()) }, hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.temporary_channel_id)) @@ -4828,7 +4925,7 @@ impl ChannelMana hash_map::Entry::Vacant(_) => break Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)) } }; - self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id); + self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id, counterparty_node_id); match res { Ok((pending_forwards, mut pending_failures, finalized_claim_htlcs, short_channel_id, channel_outpoint)) => @@ -4968,7 +5065,7 @@ impl ChannelMana } }; post_handle_chan_restoration!(self, chan_restoration_res); - self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id); + self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id, counterparty_node_id); if let Some(channel_ready_msg) = need_lnd_workaround { self.internal_channel_ready(counterparty_node_id, &channel_ready_msg)?; @@ -5066,7 +5163,11 @@ impl ChannelMana match chan.maybe_free_holding_cell_htlcs(&self.logger) { Ok((commitment_opt, holding_cell_failed_htlcs)) => { if !holding_cell_failed_htlcs.is_empty() { - failed_htlcs.push((holding_cell_failed_htlcs, *channel_id)); + failed_htlcs.push(( + holding_cell_failed_htlcs, + *channel_id, + chan.get_counterparty_node_id() + )); } if let Some((commitment_update, monitor_update)) = commitment_opt { if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) { @@ -5094,8 +5195,8 @@ impl ChannelMana } let has_update = has_monitor_update || !failed_htlcs.is_empty() || !handle_errors.is_empty(); - for (failures, channel_id) in failed_htlcs.drain(..) { - self.fail_holding_cell_htlcs(failures, channel_id); + for (failures, channel_id, counterparty_node_id) in failed_htlcs.drain(..) { + self.fail_holding_cell_htlcs(failures, channel_id, &counterparty_node_id); } for (counterparty_node_id, err) in handle_errors.drain(..) { @@ -5965,7 +6066,7 @@ impl for chan in self.list_channels() { if chan.counterparty.node_id == *counterparty_node_id { // Untrusted messages from peer, we throw away the error if id points to a non-existent channel - let _ = self.force_close_channel_with_peer(&chan.channel_id, counterparty_node_id, Some(&msg.data)); + let _ = self.force_close_channel_with_peer(&chan.channel_id, counterparty_node_id, Some(&msg.data), true); } } } else { @@ -5987,7 +6088,7 @@ impl } // Untrusted messages from peer, we throw away the error if id points to a non-existent channel - let _ = self.force_close_channel_with_peer(&msg.channel_id, counterparty_node_id, Some(&msg.data)); + let _ = self.force_close_channel_with_peer(&msg.channel_id, counterparty_node_id, Some(&msg.data), true); } } } @@ -6088,6 +6189,7 @@ impl_writeable_tlv_based!(ChannelDetails, { (4, counterparty, required), (5, outbound_scid_alias, option), (6, funding_txo, option), + (7, config, option), (8, short_channel_id, option), (10, channel_value_satoshis, required), (12, unspendable_punishment_reserve, option), @@ -6096,7 +6198,7 @@ impl_writeable_tlv_based!(ChannelDetails, { (18, outbound_capacity_msat, required), // Note that by the time we get past the required read above, outbound_capacity_msat will be // filled in, so we can safely unwrap it here. - (19, next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap())), + (19, next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap() as u64)), (20, inbound_capacity_msat, required), (22, confirmations_required, option), (24, force_close_spend_delay, option), @@ -7358,7 +7460,7 @@ mod tests { final_cltv_expiry_delta: TEST_FINAL_CLTV, }; let route = find_route( - &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), + &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, None, nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); @@ -7389,7 +7491,7 @@ mod tests { // To start (2), send a keysend payment but don't claim it. let payment_preimage = PaymentPreimage([42; 32]); let route = find_route( - &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), + &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, None, nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); @@ -7453,9 +7555,8 @@ mod tests { let scorer = test_utils::TestScorer::with_penalty(0); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let route = find_route( - &payer_pubkey, &route_params, &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), nodes[0].logger, &scorer, - &random_seed_bytes + &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::>()), + nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); let test_preimage = PaymentPreimage([42; 32]); @@ -7498,9 +7599,8 @@ mod tests { let scorer = test_utils::TestScorer::with_penalty(0); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let route = find_route( - &payer_pubkey, &route_params, &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), nodes[0].logger, &scorer, - &random_seed_bytes + &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::>()), + nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); let test_preimage = PaymentPreimage([42; 32]); @@ -7629,7 +7729,7 @@ pub mod bench { let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let mut config: UserConfig = Default::default(); - config.own_channel_config.minimum_depth = 1; + config.channel_handshake_config.minimum_depth = 1; let logger_a = test_utils::TestLogger::with_id("node a".to_owned()); let chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a);