X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=86d5bcb7318f42e2a9d8e0e7e3475411f9212ac4;hb=7f47d678587c4c5c513acc31ea1327addc157bb0;hp=f3e0ae5e09fe051707638e7964bcfe23cf43eb38;hpb=5d9f3b4fc212415c94c1b2cdff6298196ba1af51;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index f3e0ae5e..86d5bcb7 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -21,7 +21,7 @@ use bitcoin::blockdata::block::Header; use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::constants::ChainHash; use bitcoin::key::constants::SECRET_KEY_SIZE; -use bitcoin::network::constants::Network; +use bitcoin::network::Network; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; @@ -32,6 +32,7 @@ use bitcoin::secp256k1::Secp256k1; use bitcoin::{secp256k1, Sequence}; use crate::blinded_path::{BlindedPath, NodeIdLookUp}; +use crate::blinded_path::message::ForwardNode; use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs}; use crate::chain; use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock}; @@ -680,6 +681,7 @@ struct ClaimingPayment { receiver_node_id: PublicKey, htlcs: Vec, sender_intended_value: Option, + onion_fields: Option, } impl_writeable_tlv_based!(ClaimingPayment, { (0, amount_msat, required), @@ -687,6 +689,7 @@ impl_writeable_tlv_based!(ClaimingPayment, { (4, receiver_node_id, required), (5, htlcs, optional_vec), (7, sender_intended_value, option), + (9, onion_fields, option), }); struct ClaimablePayment { @@ -1167,7 +1170,7 @@ where /// /// ``` /// use bitcoin::BlockHash; -/// use bitcoin::network::constants::Network; +/// use bitcoin::network::Network; /// use lightning::chain::BestBlock; /// # use lightning::chain::channelmonitor::ChannelMonitor; /// use lightning::ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs}; @@ -1353,11 +1356,12 @@ where /// # /// # fn example(channel_manager: T) { /// # let channel_manager = channel_manager.get_cm(); +/// # let error_message = "Channel force-closed"; /// channel_manager.process_pending_events(&|event| match event { /// Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => { /// if !is_trusted(counterparty_node_id) { /// match channel_manager.force_close_without_broadcasting_txn( -/// &temporary_channel_id, &counterparty_node_id +/// &temporary_channel_id, &counterparty_node_id, error_message.to_string() /// ) { /// Ok(()) => println!("Rejecting channel {}", temporary_channel_id), /// Err(e) => println!("Error rejecting channel {}: {:?}", temporary_channel_id, e), @@ -3697,8 +3701,11 @@ where Ok(counterparty_node_id) } - fn force_close_sending_error(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool) -> Result<(), APIError> { + fn force_close_sending_error(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool, error_message: String) + -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); + log_debug!(self.logger, + "Force-closing channel, The error message sent to the peer : {}", error_message); match self.force_close_channel_with_peer(channel_id, counterparty_node_id, None, broadcast) { Ok(counterparty_node_id) => { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -3708,7 +3715,7 @@ where events::MessageSendEvent::HandleError { node_id: counterparty_node_id, action: msgs::ErrorAction::DisconnectPeer { - msg: Some(msgs::ErrorMessage { channel_id: *channel_id, data: "Channel force-closed".to_owned() }) + msg: Some(msgs::ErrorMessage { channel_id: *channel_id, data: error_message}) }, } ); @@ -3719,39 +3726,53 @@ where } } - /// 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: &ChannelId, counterparty_node_id: &PublicKey) + /// Force closes a channel, immediately broadcasting the latest local transaction(s), + /// rejecting new HTLCs. + /// + /// The provided `error_message` is sent to connected peers for closing + /// channels and should be a human-readable description of what went wrong. + /// + /// 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: &ChannelId, counterparty_node_id: &PublicKey, error_message: String) -> Result<(), APIError> { - self.force_close_sending_error(channel_id, counterparty_node_id, true) + self.force_close_sending_error(channel_id, counterparty_node_id, true, error_message) } /// 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. + /// the latest local transaction(s). + /// + /// The provided `error_message` is sent to connected peers for closing channels and should + /// be a human-readable description of what went wrong. /// + /// 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 broadcast the latest local transaction(s) via /// [`ChannelMonitor::broadcast_latest_holder_commitment_txn`]. - pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey) + pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String) -> Result<(), APIError> { - self.force_close_sending_error(channel_id, counterparty_node_id, false) + self.force_close_sending_error(channel_id, counterparty_node_id, false, error_message) } /// 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_broadcasting_latest_txn(&self) { + /// + /// The provided `error_message` is sent to connected peers for closing channels and should + /// be a human-readable description of what went wrong. + pub fn force_close_all_channels_broadcasting_latest_txn(&self, error_message: String) { for chan in self.list_channels() { - let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id); + let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id, error_message.clone()); } } /// 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) { + /// + /// The provided `error_message` is sent to connected peers for closing channels and + /// should be a human-readable description of what went wrong. + pub fn force_close_all_channels_without_broadcasting_txn(&self, error_message: String) { for chan in self.list_channels() { - let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id); + let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id, error_message.clone()); } } @@ -4632,7 +4653,7 @@ where let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let mut result = Ok(()); - if !funding_transaction.is_coin_base() { + if !funding_transaction.is_coinbase() { for inp in funding_transaction.input.iter() { if inp.witness.is_empty() { result = result.and(Err(APIError::APIMisuseError { @@ -4688,9 +4709,9 @@ where is_batch_funding, |chan, tx| { let mut output_index = None; - let expected_spk = chan.context.get_funding_redeemscript().to_v0_p2wsh(); + let expected_spk = chan.context.get_funding_redeemscript().to_p2wsh(); for (idx, outp) in tx.output.iter().enumerate() { - if outp.script_pubkey == expected_spk && outp.value == chan.context.get_value_satoshis() { + if outp.script_pubkey == expected_spk && outp.value.to_sat() == chan.context.get_value_satoshis() { if output_index.is_some() { return Err("Multiple outputs matched the expected script and value"); } @@ -6324,19 +6345,27 @@ where } } - let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(); - let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat); - let dup_purpose = claimable_payments.pending_claiming_payments.insert(payment_hash, - ClaimingPayment { amount_msat: payment.htlcs.iter().map(|source| source.value).sum(), - payment_purpose: payment.purpose, receiver_node_id, htlcs, sender_intended_value - }); - if dup_purpose.is_some() { - debug_assert!(false, "Shouldn't get a duplicate pending claim event ever"); - log_error!(self.logger, "Got a duplicate pending claimable event on payment hash {}! Please report this bug", - &payment_hash); - } + let claiming_payment = claimable_payments.pending_claiming_payments + .entry(payment_hash) + .and_modify(|_| { + debug_assert!(false, "Shouldn't get a duplicate pending claim event ever"); + log_error!(self.logger, "Got a duplicate pending claimable event on payment hash {}! Please report this bug", + &payment_hash); + }) + .or_insert_with(|| { + let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(); + let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat); + ClaimingPayment { + amount_msat: payment.htlcs.iter().map(|source| source.value).sum(), + payment_purpose: payment.purpose, + receiver_node_id, + htlcs, + sender_intended_value, + onion_fields: payment.onion_fields, + } + }); - if let Some(RecipientOnionFields { ref custom_tlvs, .. }) = payment.onion_fields { + if let Some(RecipientOnionFields { ref custom_tlvs, .. }) = claiming_payment.onion_fields { if !custom_tlvs_known && custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) { log_info!(self.logger, "Rejecting payment with payment hash {} as we cannot accept payment with unknown even TLVs: {}", &payment_hash, log_iter!(custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0))); @@ -6743,6 +6772,7 @@ where receiver_node_id, htlcs, sender_intended_value: sender_intended_total_msat, + onion_fields, }) = payment { self.pending_events.lock().unwrap().push_back((events::Event::PaymentClaimed { payment_hash, @@ -6751,6 +6781,7 @@ where receiver_node_id: Some(receiver_node_id), htlcs, sender_intended_total_msat, + onion_fields, }, None)); } }, @@ -7250,7 +7281,7 @@ where match phase.get_mut() { ChannelPhase::UnfundedOutboundV1(chan) => { try_chan_phase_entry!(self, chan.accept_channel(&msg, &self.default_configuration.channel_handshake_limits, &peer_state.latest_features), phase); - (chan.context.get_value_satoshis(), chan.context.get_funding_redeemscript().to_v0_p2wsh(), chan.context.get_user_id()) + (chan.context.get_value_satoshis(), chan.context.get_funding_redeemscript().to_p2wsh(), chan.context.get_user_id()) }, _ => { return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got an unexpected accept_channel message from peer with counterparty_node_id {}", counterparty_node_id), msg.common_fields.temporary_channel_id)); @@ -8996,8 +9027,16 @@ where let peers = self.per_peer_state.read().unwrap() .iter() - .filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_onion_messages()) - .map(|(node_id, _)| *node_id) + .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap())) + .filter(|(_, peer)| peer.latest_features.supports_onion_messages()) + .map(|(node_id, peer)| ForwardNode { + node_id: *node_id, + short_channel_id: peer.channel_by_id + .iter() + .filter(|(_, channel)| channel.context().is_usable()) + .min_by_key(|(_, channel)| channel.context().channel_creation_height) + .and_then(|(_, channel)| channel.context().get_short_channel_id()), + }) .collect::>(); self.router @@ -12264,6 +12303,7 @@ where amount_msat: claimable_amt_msat, htlcs: payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(), sender_intended_total_msat: payment.htlcs.first().map(|htlc| htlc.total_msat), + onion_fields: payment.onion_fields, }, None)); } } @@ -12947,8 +12987,8 @@ mod tests { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id()); - - nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()).unwrap(); + let error_message = "Channel force-closed"; + nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); @@ -13165,6 +13205,7 @@ mod tests { let channel_id = ChannelId::from_bytes([4; 32]); let unkown_public_key = PublicKey::from_secret_key(&Secp256k1::signing_only(), &SecretKey::from_slice(&[42; 32]).unwrap()); let intercept_id = InterceptId([0; 32]); + let error_message = "Channel force-closed"; // Test the API functions. check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None, None), unkown_public_key); @@ -13173,9 +13214,9 @@ mod tests { check_unkown_peer_error(nodes[0].node.close_channel(&channel_id, &unkown_public_key), unkown_public_key); - check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key), unkown_public_key); + check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key, error_message.to_string()), unkown_public_key); - check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key), unkown_public_key); + check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key, error_message.to_string()), unkown_public_key); check_unkown_peer_error(nodes[0].node.forward_intercepted_htlc(intercept_id, &channel_id, unkown_public_key, 1_000_000), unkown_public_key); @@ -13197,15 +13238,16 @@ mod tests { // Dummy values let channel_id = ChannelId::from_bytes([4; 32]); + let error_message = "Channel force-closed"; // Test the API functions. check_api_misuse_error(nodes[0].node.accept_inbound_channel(&channel_id, &counterparty_node_id, 42)); check_channel_unavailable_error(nodes[0].node.close_channel(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id); - check_channel_unavailable_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id); + check_channel_unavailable_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id, error_message.to_string()), channel_id, counterparty_node_id); - check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id); + check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id, error_message.to_string()), channel_id, counterparty_node_id); check_channel_unavailable_error(nodes[0].node.forward_intercepted_htlc(InterceptId([0; 32]), &channel_id, counterparty_node_id, 1_000_000), channel_id, counterparty_node_id); @@ -13559,6 +13601,7 @@ mod tests { anchors_config.manually_accept_inbound_channels = true; let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config.clone())]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + let error_message = "Channel force-closed"; nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); @@ -13568,7 +13611,7 @@ mod tests { let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id()).unwrap(); + nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); } _ => panic!("Unexpected event"), } @@ -13676,12 +13719,13 @@ mod tests { let user_config = test_default_channel_config(); let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfg, &node_chanmgr); + let error_message = "Channel force-closed"; // Open a channel, immediately disconnect each other, and broadcast Alice's latest state. let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id()); - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); @@ -13802,10 +13846,12 @@ pub mod bench { use crate::util::test_utils; use crate::util::config::{UserConfig, MaxDustHTLCExposure}; + use bitcoin::amount::Amount; use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::{Transaction, TxOut}; + use bitcoin::transaction::Version; use crate::sync::{Arc, Mutex, RwLock}; @@ -13882,8 +13928,8 @@ pub mod bench { let tx; if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = get_event!(node_a_holder, Event::FundingGenerationReady) { - tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 8_000_000, script_pubkey: output_script, + tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { + value: Amount::from_sat(8_000_000), script_pubkey: output_script, }]}; node_a.funding_transaction_generated(&temporary_channel_id, &node_b.get_our_node_id(), tx.clone()).unwrap(); } else { panic!(); }