use super::packet::ParsedOnionMessageContents;
use super::offers::OffersMessageHandler;
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
-use crate::util::logger::Logger;
+use crate::util::logger::{Logger, WithContext};
use crate::util::ser::Writeable;
use core::fmt;
const MIN_PEER_CHANNELS: usize = 3;
let network_graph = self.network_graph.deref().read_only();
+ let is_recipient_announced =
+ network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient));
+
let mut peer_info = peers.iter()
// Limit to peers with announced channels
.filter_map(|pubkey|
network_graph
.node(&NodeId::from_pubkey(pubkey))
.filter(|info| info.channels.len() >= MIN_PEER_CHANNELS)
- .map(|info| (*pubkey, info.is_tor_only()))
+ .map(|info| (*pubkey, info.is_tor_only(), info.channels.len()))
)
+ // Exclude Tor-only nodes when the recipient is announced.
+ .filter(|(_, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
.collect::<Vec<_>>();
- peer_info.sort_unstable_by(|(_, a_tor_only), (_, b_tor_only)| a_tor_only.cmp(b_tor_only));
+
+ // Prefer using non-Tor nodes with the most channels as the introduction node.
+ peer_info.sort_unstable_by(|(_, a_tor_only, a_channels), (_, b_tor_only, b_channels)| {
+ a_tor_only.cmp(b_tor_only).then(a_channels.cmp(b_channels).reverse())
+ });
let paths = peer_info.into_iter()
- .map(|(pubkey, _)| vec![pubkey, recipient])
+ .map(|(pubkey, _, _)| vec![pubkey, recipient])
.map(|node_pks| BlindedPath::new_for_message(&node_pks, &*self.entropy_source, secp_ctx))
.take(MAX_PATHS)
.collect::<Result<Vec<_>, _>>();
match paths {
Ok(paths) if !paths.is_empty() => Ok(paths),
_ => {
- if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) {
+ if is_recipient_announced {
BlindedPath::one_hop_for_message(recipient, &*self.entropy_source, secp_ctx)
.map(|path| vec![path])
} else {
&self, contents: T, destination: Destination, reply_path: Option<BlindedPath>,
log_suffix: fmt::Arguments
) -> Result<SendSuccess, SendError> {
+ let mut logger = WithContext::from(&self.logger, None, None);
let result = self.find_path(destination)
- .and_then(|path| self.enqueue_onion_message(path, contents, reply_path, log_suffix));
+ .and_then(|path| {
+ let first_hop = path.intermediate_nodes.get(0).map(|p| *p);
+ logger = WithContext::from(&self.logger, first_hop, None);
+ self.enqueue_onion_message(path, contents, reply_path, log_suffix)
+ });
match result.as_ref() {
Err(SendError::GetNodeIdFailed) => {
- log_warn!(self.logger, "Unable to retrieve node id {}", log_suffix);
+ log_warn!(logger, "Unable to retrieve node id {}", log_suffix);
},
Err(SendError::PathNotFound) => {
- log_trace!(self.logger, "Failed to find path {}", log_suffix);
+ log_trace!(logger, "Failed to find path {}", log_suffix);
},
Err(e) => {
- log_trace!(self.logger, "Failed sending onion message {}: {:?}", log_suffix, e);
+ log_trace!(logger, "Failed sending onion message {}: {:?}", log_suffix, e);
},
Ok(SendSuccess::Buffered) => {
- log_trace!(self.logger, "Buffered onion message {}", log_suffix);
+ log_trace!(logger, "Buffered onion message {}", log_suffix);
},
Ok(SendSuccess::BufferedAwaitingConnection(node_id)) => {
log_trace!(
- self.logger, "Buffered onion message waiting on peer connection {}: {:?}",
+ logger,
+ "Buffered onion message waiting on peer connection {}: {}",
log_suffix, node_id
);
},
OMH::Target: OffersMessageHandler,
CMH::Target: CustomOnionMessageHandler,
{
- fn handle_onion_message(&self, _peer_node_id: &PublicKey, msg: &OnionMessage) {
+ fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
+ let logger = WithContext::from(&self.logger, Some(*peer_node_id), None);
match self.peel_onion_message(msg) {
Ok(PeeledOnion::Receive(message, path_id, reply_path)) => {
log_trace!(
- self.logger,
- "Received an onion message with path_id {:02x?} and {} reply_path: {:?}",
+ logger,
+ "Received an onion message with path_id {:02x?} and {} reply_path: {:?}",
path_id, if reply_path.is_some() { "a" } else { "no" }, message);
match message {
Ok(PeeledOnion::Forward(next_node_id, onion_message)) => {
let mut message_recipients = self.message_recipients.lock().unwrap();
if outbound_buffer_full(&next_node_id, &message_recipients) {
- log_trace!(self.logger, "Dropping forwarded onion message to peer {:?}: outbound buffer full", next_node_id);
+ log_trace!(
+ logger,
+ "Dropping forwarded onion message to peer {}: outbound buffer full",
+ next_node_id);
return
}
e.get(), OnionMessageRecipient::ConnectedPeer(..)
) => {
e.get_mut().enqueue_message(onion_message);
- log_trace!(self.logger, "Forwarding an onion message to peer {}", next_node_id);
+ log_trace!(logger, "Forwarding an onion message to peer {}", next_node_id);
},
_ => {
- log_trace!(self.logger, "Dropping forwarded onion message to disconnected peer {:?}", next_node_id);
+ log_trace!(
+ logger,
+ "Dropping forwarded onion message to disconnected peer {}",
+ next_node_id);
return
},
}
},
Err(e) => {
- log_error!(self.logger, "Failed to process onion message {:?}", e);
+ log_error!(logger, "Failed to process onion message {:?}", e);
}
}
}