1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00
This commit is contained in:
jeff (codeaholic) 2023-08-23 05:24:10 -07:00 committed by GitHub
commit 3e91583a16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 144 additions and 26 deletions

View file

@ -145,6 +145,7 @@ add_library(lokinet-config
# lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients
add_library(lokinet-consensus
STATIC
consensus/edge_selector.cpp
consensus/reachability_testing.cpp
)

View file

@ -0,0 +1,71 @@
#include "edge_selector.hpp"
#include <llarp/router/abstractrouter.hpp>
#include <llarp/crypto/crypto.hpp>
#include <llarp/nodedb.hpp>
#include <llarp/profiling.hpp>
namespace llarp::consensus
{
EdgeSelector::EdgeSelector(AbstractRouter& r) : _router{r}
{}
std::optional<RouterContact>
EdgeSelector::select_path_edge(const std::unordered_set<RouterID>& connected_now) const
{
auto conf = _router.GetConfig();
auto nodedb = _router.nodedb();
const auto& _keys = conf->network.m_strictConnect;
// no strict hops. select a random good snode.
if (_keys.empty())
{
return nodedb->GetRandom([&connected_now, this](const auto& rc) {
return connected_now.count(rc.pubkey) == 0
and not _router.routerProfiling().IsBadForConnect(rc.pubkey)
and not _router.IsBootstrapNode(rc.pubkey);
});
}
// select random from strict connections.
std::vector<RouterID> keys{_keys.begin(), _keys.end()};
std::shuffle(keys.begin(), keys.end(), llarp::CSRNG{});
for (const auto& pk : keys)
{
if (_router.routerProfiling().IsBadForConnect(pk))
continue;
if (connected_now.count(pk))
continue;
if (auto maybe = nodedb->Get(pk))
return maybe;
}
return std::nullopt;
}
std::optional<RouterContact>
EdgeSelector::select_bootstrap(const std::unordered_set<RouterID>& connected_now) const
{
auto conf = _router.GetConfig();
auto nodedb = _router.nodedb();
if (const auto& _keys = conf->network.m_strictConnect; not _keys.empty())
{
// try bootstrapping off strict connections first if we have any.
std::vector<RouterID> keys{_keys.begin(), _keys.end()};
std::shuffle(keys.begin(), keys.end(), llarp::CSRNG{});
for (const auto& pk : keys)
{
if (connected_now.count(pk))
continue;
if (auto maybe = nodedb->Get(pk))
return maybe;
}
}
// if we cant use a strict connection we'll just use one of our bootstrap nodes.
return nodedb->GetRandom([&connected_now, this](const auto& rc) {
return connected_now.count(rc.pubkey) == 0 and _router.IsBootstrapNode(rc.pubkey);
});
}
} // namespace llarp::consensus

View file

@ -0,0 +1,35 @@
#pragma once
#include <optional>
#include <unordered_set>
#include <llarp/router_id.hpp>
namespace llarp
{
struct AbstractRouter;
struct RouterContact;
} // namespace llarp
namespace llarp::consensus
{
/// when we want to connect to and edge when we are a client, an instance of EdgeSelector acts as
/// a stateless selection algorith for router contacts for each attempt at connecting out we make.
class EdgeSelector
{
AbstractRouter& _router;
public:
explicit EdgeSelector(AbstractRouter& router);
/// select a candidate for connecting out to the network when we need more connections to do a
/// path build. pass in an unordered set of the snode pubkeys we are currently connected to.
std::optional<RouterContact>
select_path_edge(const std::unordered_set<RouterID>& connected_now = {}) const;
/// get a router contact of a bootstrap snode to bootstrap with if we are in need of
/// bootstrapping more peers. pass in an unodereed set of bootstrap router pubkeys we are
/// currently connected to.
std::optional<RouterContact>
select_bootstrap(const std::unordered_set<RouterID>& connected_now = {}) const;
};
} // namespace llarp::consensus

View file

@ -45,6 +45,11 @@ namespace llarp
struct I_RCLookupHandler;
struct RoutePoker;
namespace consensus
{
class EdgeSelector;
}
namespace dns
{
class I_SystemSettings;
@ -130,6 +135,9 @@ namespace llarp
virtual const RouterContact&
rc() const = 0;
virtual const consensus::EdgeSelector&
edge_selector() const = 0;
/// modify our rc
/// modify returns nullopt if unmodified otherwise it returns the new rc to be sigend and
/// published out

View file

@ -11,6 +11,7 @@
#include <llarp/util/thread/threading.hpp>
#include <llarp/util/status.hpp>
#include <llarp/crypto/crypto.hpp>
#include <llarp/consensus/edge_selector.hpp>
#include <utility>
#include <llarp/rpc/lokid_rpc_client.hpp>
@ -139,30 +140,23 @@ namespace llarp
OutboundSessionMaker::ConnectToRandomRouters(int numDesired)
{
int remainingDesired = numDesired;
std::set<RouterID> exclude;
std::unordered_set<RouterID> exclude;
for (const auto& item : pendingSessions)
exclude.emplace(item.first);
_linkManager->ForEachPeer([&exclude](auto* session) {
if (session and session->IsEstablished())
exclude.emplace(session->GetPubKey());
});
do
{
auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; };
RouterContact other;
if (const auto maybe = _nodedb->GetRandom(filter))
{
other = *maybe;
}
else
auto maybe_rc = _router->edge_selector().select_path_edge(exclude);
if (not maybe_rc)
break;
exclude.insert(other.pubkey);
if (not _rcLookup->SessionIsAllowed(other.pubkey))
{
continue;
}
if (not(_linkManager->HasSessionTo(other.pubkey) || HavePendingSessionTo(other.pubkey)))
{
CreateSessionTo(other, nullptr);
--remainingDesired;
}
const auto& rc = *maybe_rc;
exclude.insert(rc.pubkey);
CreateSessionTo(rc, nullptr);
--remainingDesired;
} while (remainingDesired > 0);
LogDebug(
"connecting to ", numDesired - remainingDesired, " out of ", numDesired, " random routers");

View file

@ -50,6 +50,7 @@ namespace llarp
Router::Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform)
: ready{false}
, m_lmq{std::make_shared<oxenmq::OxenMQ>()}
, _edge_selector{*this}
, _loop{std::move(loop)}
, _vpnPlatform{std::move(vpnPlatform)}
, paths{this}
@ -869,6 +870,12 @@ namespace llarp
m_LastStatsReport = now;
}
const consensus::EdgeSelector&
Router::edge_selector() const
{
return _edge_selector;
}
std::string
Router::status_line()
{
@ -1059,12 +1066,8 @@ namespace llarp
_rcLookupHandler.ExploreNetwork();
m_NextExploreAt = timepoint_now + std::chrono::seconds(interval);
}
size_t connectToNum = _outboundSessionMaker.minConnectedRouters;
const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters();
if (strictConnect > 0 && connectToNum > strictConnect)
{
connectToNum = strictConnect;
}
size_t connectToNum = _outboundSessionMaker.maxConnectedRouters;
if (isSvcNode and now >= m_NextDecommissionWarn)
{

View file

@ -3,6 +3,7 @@
#include "abstractrouter.hpp"
#include <llarp/bootstrap.hpp>
#include <llarp/consensus/edge_selector.hpp>
#include <llarp/config/config.hpp>
#include <llarp/config/key_manager.hpp>
#include <llarp/constants/link_layer.hpp>
@ -79,6 +80,8 @@ namespace llarp
std::shared_ptr<EventLoopWakeup> m_Pump;
consensus::EdgeSelector _edge_selector;
path::BuildLimiter&
pathBuildLimiter() override
{
@ -148,6 +151,9 @@ namespace llarp
const std::vector<RouterID>& greylist,
const std::vector<RouterID>& unfunded) override;
const consensus::EdgeSelector&
edge_selector() const override;
std::unordered_set<RouterID>
GetRouterWhitelist() const override
{