Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix peer connect race #121

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 55 additions & 2 deletions src/onion_messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ use std::io::Cursor;
use std::marker::Copy;
use std::str::FromStr;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::{select, time, time::Duration, time::Interval};
use tokio::time::{sleep, timeout, Duration, Interval};
use tokio::{select, time};
use tonic_lnd::lnrpc::ChanInfoRequest;
use tonic_lnd::Client;
use tonic_lnd::{
Expand Down Expand Up @@ -331,7 +332,26 @@ async fn lookup_onion_support(pubkey: &PublicKey, client: &mut tonic_lnd::Lightn
continue;
}

return features_support_onion_messages(&peer.features);
// Sometimes if the connection to the peer is very new, we have to wait for the
// features map to populate as non-empty.
let check_empty_timeout = 5;
let features = match timeout(
Duration::from_secs(check_empty_timeout),
check_empty_features(pubkey, client.clone()),
)
.await
{
Ok(features) => features,
Err(_) => {
warn!(
"Did not get non-empty feature set from peer {} set in {} seconds.",
peer.pub_key, check_empty_timeout
);
peer.features
}
};

return features_support_onion_messages(&features);
}

warn!("Peer {pubkey} not found in current set of peers, assuming no onion support.");
Expand All @@ -344,6 +364,39 @@ async fn lookup_onion_support(pubkey: &PublicKey, client: &mut tonic_lnd::Lightn
}
}

// check_empty_features repeatedly looks up the peer's feature set until it returns a non-empty
// map. Sometimes if a peer is new, LND needs a little time to update the feature set.
async fn check_empty_features(
pubkey: &PublicKey,
mut client: LightningClient,
) -> HashMap<u32, tonic_lnd::lnrpc::Feature> {
loop {
match client
.list_peers(tonic_lnd::lnrpc::ListPeersRequest {
latest_error: false,
})
.await
{
Ok(peers) => {
for peer in peers.into_inner().peers {
if peer.pub_key != pubkey.to_string() {
continue;
}

if !peer.features.is_empty() {
return peer.features;
}
}
}
Err(_) => {
warn!("error connecting to listpeers");
continue;
}
};
sleep(Duration::from_millis(500)).await;
}
}

#[derive(Debug)]
/// ProducerError represents the exit of a producing loop.
enum ProducerError {
Expand Down
Loading