mirror of https://github.com/oxen-io/lokinet
commit
d520e1d2c4
@ -1,151 +0,0 @@
|
||||
#include "rc_gossiper.hpp"
|
||||
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/util/time.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
// 30 minutes
|
||||
static constexpr auto RCGossipFilterDecayInterval = 30min;
|
||||
// (30 minutes * 2) - 5 minutes
|
||||
static constexpr auto GossipOurRCInterval = (RCGossipFilterDecayInterval * 2) - (5min);
|
||||
|
||||
RCGossiper::RCGossiper() : filter(std::chrono::duration_cast<Time_t>(RCGossipFilterDecayInterval))
|
||||
{}
|
||||
|
||||
void
|
||||
RCGossiper::Init(LinkManager* l, const RouterID& ourID, Router* r)
|
||||
{
|
||||
rid = ourID;
|
||||
link_manager = l;
|
||||
router = r;
|
||||
}
|
||||
|
||||
bool
|
||||
RCGossiper::ShouldGossipOurRC(Time_t now) const
|
||||
{
|
||||
return now >= (last_rc_gossip + GossipOurRCInterval);
|
||||
}
|
||||
|
||||
bool
|
||||
RCGossiper::IsOurRC(const LocalRC& rc) const
|
||||
{
|
||||
return rc.router_id() == rid;
|
||||
}
|
||||
|
||||
void
|
||||
RCGossiper::Decay(Time_t now)
|
||||
{
|
||||
filter.Decay(now);
|
||||
}
|
||||
|
||||
void
|
||||
RCGossiper::Forget(const RouterID& pk)
|
||||
{
|
||||
filter.Remove(pk);
|
||||
if (rid == pk)
|
||||
last_rc_gossip = 0s;
|
||||
}
|
||||
|
||||
TimePoint_t
|
||||
RCGossiper::NextGossipAt() const
|
||||
{
|
||||
if (auto maybe = LastGossipAt())
|
||||
return *maybe + GossipOurRCInterval;
|
||||
return DateClock_t::now();
|
||||
}
|
||||
|
||||
std::optional<TimePoint_t>
|
||||
RCGossiper::LastGossipAt() const
|
||||
{
|
||||
if (last_rc_gossip == 0s)
|
||||
return std::nullopt;
|
||||
return DateClock_t::time_point{last_rc_gossip};
|
||||
}
|
||||
|
||||
bool
|
||||
RCGossiper::GossipRC(const LocalRC& rc)
|
||||
{
|
||||
// only distribute public routers
|
||||
if (not rc.is_public_router())
|
||||
return false;
|
||||
if (link_manager == nullptr)
|
||||
return false;
|
||||
const RouterID pubkey(rc.router_id());
|
||||
// filter check
|
||||
if (filter.Contains(pubkey))
|
||||
return false;
|
||||
filter.Insert(pubkey);
|
||||
|
||||
const auto now = time_now_ms();
|
||||
// is this our rc?
|
||||
if (IsOurRC(rc))
|
||||
{
|
||||
// should we gossip our rc?
|
||||
if (not ShouldGossipOurRC(now))
|
||||
{
|
||||
// nah drop it
|
||||
return false;
|
||||
}
|
||||
// ya pop it
|
||||
last_rc_gossip = now;
|
||||
}
|
||||
|
||||
// send a GRCM as gossip method
|
||||
// DHTImmediateMessage gossip;
|
||||
// gossip.msgs.emplace_back(new dht::GotRouterMessage(dht::Key_t{}, 0, {rc}, false));
|
||||
|
||||
// std::vector<RouterID> gossipTo;
|
||||
|
||||
/*
|
||||
* TODO: gossip RC via libquic
|
||||
*
|
||||
// select peers to gossip to
|
||||
m_LinkManager->ForEachPeer(
|
||||
[&](const AbstractLinkSession* peerSession, bool) {
|
||||
// ensure connected session
|
||||
if (not(peerSession && peerSession->IsEstablished()))
|
||||
return;
|
||||
// check if public router
|
||||
const auto other_rc = peerSession->GetRemoteRC();
|
||||
if (not other_rc.IsPublicRouter())
|
||||
return;
|
||||
gossipTo.emplace_back(other_rc.pubkey);
|
||||
},
|
||||
true);
|
||||
|
||||
std::unordered_set<RouterID> keys;
|
||||
// grab the keys we want to use
|
||||
std::sample(
|
||||
gossipTo.begin(), gossipTo.end(), std::inserter(keys, keys.end()), MaxGossipPeers,
|
||||
llarp::csrng);
|
||||
|
||||
m_LinkManager->ForEachPeer([&](AbstractLinkSession* peerSession) {
|
||||
if (not(peerSession && peerSession->IsEstablished()))
|
||||
return;
|
||||
|
||||
// exclude from gossip as we have not selected to use it
|
||||
if (keys.count(peerSession->GetPubKey()) == 0)
|
||||
return;
|
||||
|
||||
// encode message
|
||||
AbstractLinkSession::Message_t msg{};
|
||||
msg.resize(MAX_LINK_MSG_SIZE / 2);
|
||||
llarp_buffer_t buf(msg);
|
||||
if (not gossip.BEncode(&buf))
|
||||
return;
|
||||
msg.resize(buf.cur - buf.base);
|
||||
|
||||
m_router->NotifyRouterEvent<tooling::RCGossipSentEvent>(m_router->pubkey(), rc);
|
||||
|
||||
// send message
|
||||
peerSession->SendMessageBuffer(std::move(msg), nullptr, gossip.Priority());
|
||||
});
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/util/decaying_hashset.hpp>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct Router;
|
||||
|
||||
/// The maximum number of peers we will flood a gossiped RC to when propagating an RC
|
||||
constexpr size_t MaxGossipPeers = 20;
|
||||
struct LinkManager;
|
||||
struct LocalRC;
|
||||
|
||||
struct RCGossiper
|
||||
{
|
||||
using Time_t = Duration_t;
|
||||
|
||||
RCGossiper();
|
||||
|
||||
~RCGossiper() = default;
|
||||
|
||||
bool
|
||||
GossipRC(const LocalRC& rc);
|
||||
|
||||
void
|
||||
Decay(Time_t now);
|
||||
|
||||
bool
|
||||
ShouldGossipOurRC(Time_t now) const;
|
||||
|
||||
bool
|
||||
IsOurRC(const LocalRC& rc) const;
|
||||
|
||||
void
|
||||
Init(LinkManager*, const RouterID&, Router*);
|
||||
|
||||
void
|
||||
Forget(const RouterID& router);
|
||||
|
||||
TimePoint_t
|
||||
NextGossipAt() const;
|
||||
|
||||
std::optional<TimePoint_t>
|
||||
LastGossipAt() const;
|
||||
|
||||
private:
|
||||
RouterID rid;
|
||||
Time_t last_rc_gossip = 0s;
|
||||
LinkManager* link_manager = nullptr;
|
||||
util::DecayingHashSet<RouterID> filter;
|
||||
|
||||
Router* router;
|
||||
};
|
||||
} // namespace llarp
|
@ -1,357 +0,0 @@
|
||||
#include "rc_lookup_handler.hpp"
|
||||
|
||||
#include "router.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/link/contacts.hpp>
|
||||
#include <llarp/link/link_manager.hpp>
|
||||
#include <llarp/nodedb.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/service/context.hpp>
|
||||
#include <llarp/util/types.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
void
|
||||
RCLookupHandler::add_valid_router(const RouterID& rid)
|
||||
{
|
||||
router->loop()->call([this, rid]() { router_whitelist.insert(rid); });
|
||||
}
|
||||
|
||||
void
|
||||
RCLookupHandler::remove_valid_router(const RouterID& rid)
|
||||
{
|
||||
router->loop()->call([this, rid]() { router_whitelist.erase(rid); });
|
||||
}
|
||||
|
||||
static void
|
||||
loadColourList(std::unordered_set<RouterID>& beigelist, const std::vector<RouterID>& new_beige)
|
||||
{
|
||||
beigelist.clear();
|
||||
beigelist.insert(new_beige.begin(), new_beige.end());
|
||||
}
|
||||
|
||||
void
|
||||
RCLookupHandler::set_router_whitelist(
|
||||
const std::vector<RouterID>& whitelist,
|
||||
const std::vector<RouterID>& greylist,
|
||||
const std::vector<RouterID>& greenlist)
|
||||
{
|
||||
if (whitelist.empty())
|
||||
return;
|
||||
|
||||
router->loop()->call([this, whitelist, greylist, greenlist]() {
|
||||
loadColourList(router_whitelist, whitelist);
|
||||
loadColourList(router_greylist, greylist);
|
||||
loadColourList(router_greenlist, greenlist);
|
||||
LogInfo("lokinet service node list now has ", router_whitelist.size(), " active routers");
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::has_received_whitelist() const
|
||||
{
|
||||
return router->loop()->call_get([this]() { return not router_whitelist.empty(); });
|
||||
}
|
||||
|
||||
std::unordered_set<RouterID>
|
||||
RCLookupHandler::whitelist() const
|
||||
{
|
||||
return router->loop()->call_get([this]() { return router_whitelist; });
|
||||
}
|
||||
|
||||
void
|
||||
RCLookupHandler::get_rc(const RouterID& rid, RCRequestCallback callback, bool forceLookup)
|
||||
{
|
||||
(void)rid;
|
||||
(void)callback;
|
||||
(void)forceLookup;
|
||||
/* RC refactor pending, this will likely go away entirely
|
||||
*
|
||||
*
|
||||
RemoteRC remoteRC;
|
||||
|
||||
if (not forceLookup)
|
||||
{
|
||||
if (const auto maybe = node_db->get_rc(rid); maybe.has_value())
|
||||
{
|
||||
remoteRC = *maybe;
|
||||
|
||||
if (callback)
|
||||
{
|
||||
callback(rid, remoteRC, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto lookup_cb = [this, callback, rid](RemoteRC rc, bool success) mutable {
|
||||
auto& r = link_manager->router();
|
||||
|
||||
if (not success)
|
||||
{
|
||||
if (callback)
|
||||
callback(rid, std::nullopt, false);
|
||||
return;
|
||||
}
|
||||
|
||||
r.node_db()->put_rc_if_newer(rc);
|
||||
if (callback)
|
||||
callback(rc.router_id(), rc, true);
|
||||
};
|
||||
|
||||
// TODO: RC fetching and gossiping in general is being refactored, and the old method
|
||||
// of look it up over a path or directly but using the same method but called
|
||||
// differently is going away. It's a mess. The below will do a lookup via a path,
|
||||
// relays will need a different implementation TBD.
|
||||
if (!isServiceNode)
|
||||
hidden_service_context->GetDefault()->lookup_router(rid, std::move(lookup_cb));
|
||||
*/
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::is_grey_listed(const RouterID& remote) const
|
||||
{
|
||||
if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0
|
||||
&& !is_remote_in_bootstrap(remote))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not isServiceNode)
|
||||
return false;
|
||||
|
||||
return router->loop()->call_get([this, remote]() { return router_greylist.count(remote); });
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::is_green_listed(const RouterID& remote) const
|
||||
{
|
||||
return router->loop()->call_get([this, remote]() { return router_greenlist.count(remote); });
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::is_registered(const RouterID& rid) const
|
||||
{
|
||||
return router->loop()->call_get([this, rid]() {
|
||||
return router_whitelist.count(rid) || router_greylist.count(rid)
|
||||
|| router_greenlist.count(rid);
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::is_path_allowed(const RouterID& rid) const
|
||||
{
|
||||
return router->loop()->call_get([this, rid]() {
|
||||
if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(rid) == 0
|
||||
&& !is_remote_in_bootstrap(rid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not isServiceNode)
|
||||
return true;
|
||||
|
||||
return router_whitelist.count(rid) != 0;
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::is_session_allowed(const RouterID& rid) const
|
||||
{
|
||||
return router->loop()->call_get([this, rid]() {
|
||||
if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(rid) == 0
|
||||
&& !is_remote_in_bootstrap(rid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not isServiceNode)
|
||||
return true;
|
||||
|
||||
return router_whitelist.count(rid) or router_greylist.count(rid);
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::check_rc(const RemoteRC& rc) const
|
||||
{
|
||||
if (not is_session_allowed(rc.router_id()))
|
||||
{
|
||||
contacts->delete_rc_node_async(dht::Key_t{rc.router_id()});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not rc.verify())
|
||||
{
|
||||
log::info(link_cat, "Invalid RC (rid: {})", rc.router_id());
|
||||
return false;
|
||||
}
|
||||
|
||||
// update nodedb if required
|
||||
if (rc.is_public_router())
|
||||
{
|
||||
log::info(link_cat, "Adding or updating RC (rid: {}) to nodeDB and DHT", rc.router_id());
|
||||
node_db->put_rc_if_newer(rc);
|
||||
contacts->put_rc_node_async(rc);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
RCLookupHandler::num_strict_connect_routers() const
|
||||
{
|
||||
return strict_connect_pubkeys.size();
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::get_random_whitelist_router(RouterID& rid) const
|
||||
{
|
||||
return router->loop()->call_get([this, rid]() mutable {
|
||||
const auto sz = router_whitelist.size();
|
||||
auto itr = router_whitelist.begin();
|
||||
if (sz == 0)
|
||||
return false;
|
||||
if (sz > 1)
|
||||
std::advance(itr, randint() % sz);
|
||||
rid = *itr;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
RCLookupHandler::periodic_update(llarp_time_t now)
|
||||
{
|
||||
// try looking up stale routers
|
||||
std::unordered_set<RouterID> routersToLookUp;
|
||||
|
||||
node_db->VisitInsertedBefore(
|
||||
[&](const RouterContact& rc) { routersToLookUp.insert(rc.router_id()); },
|
||||
now - RouterContact::REPUBLISH);
|
||||
|
||||
for (const auto& router : routersToLookUp)
|
||||
{
|
||||
get_rc(router, nullptr, true);
|
||||
}
|
||||
|
||||
node_db->remove_stale_rcs(boostrap_rid_list, now - RouterContact::STALE);
|
||||
}
|
||||
|
||||
void
|
||||
RCLookupHandler::explore_network()
|
||||
{
|
||||
const size_t known = node_db->num_loaded();
|
||||
if (bootstrap_rc_list.empty() && known == 0)
|
||||
{
|
||||
LogError("we have no bootstrap nodes specified");
|
||||
}
|
||||
else if (known <= bootstrap_rc_list.size())
|
||||
{
|
||||
for (const auto& rc : bootstrap_rc_list)
|
||||
{
|
||||
const auto& rid = rc.router_id();
|
||||
log::info(link_cat, "Doing explore via bootstrap node: {}", rid);
|
||||
|
||||
// TODO: replace this concept
|
||||
// dht->ExploreNetworkVia(dht::Key_t{rc.pubkey});
|
||||
}
|
||||
}
|
||||
|
||||
if (isServiceNode)
|
||||
{
|
||||
static constexpr size_t LookupPerTick = 5;
|
||||
|
||||
std::vector<RouterID> lookup_routers = router->loop()->call_get([this]() {
|
||||
std::vector<RouterID> lookups;
|
||||
lookups.reserve(LookupPerTick);
|
||||
|
||||
for (const auto& r : router_whitelist)
|
||||
{
|
||||
if (not node_db->has_router(r))
|
||||
lookups.emplace_back(r);
|
||||
}
|
||||
|
||||
return lookups;
|
||||
});
|
||||
|
||||
if (lookup_routers.size() > LookupPerTick)
|
||||
{
|
||||
std::shuffle(lookup_routers.begin(), lookup_routers.end(), llarp::csrng);
|
||||
lookup_routers.resize(LookupPerTick);
|
||||
}
|
||||
|
||||
for (const auto& r : lookup_routers)
|
||||
get_rc(r, nullptr, true);
|
||||
return;
|
||||
}
|
||||
// service nodes gossip, not explore
|
||||
if (contacts->router()->is_service_node())
|
||||
return;
|
||||
|
||||
// explore via every connected peer
|
||||
/*
|
||||
* TODO: DHT explore via libquic
|
||||
*
|
||||
_linkManager->ForEachPeer([&](ILinkSession* s) {
|
||||
if (!s->IsEstablished())
|
||||
return;
|
||||
const RouterContact rc = s->GetRemoteRC();
|
||||
if (rc.IsPublicRouter() && (_bootstrapRCList.find(rc) == _bootstrapRCList.end()))
|
||||
{
|
||||
LogDebug("Doing explore via public node: ", RouterID(rc.pubkey));
|
||||
_dht->impl->ExploreNetworkVia(dht::Key_t{rc.pubkey});
|
||||
}
|
||||
});
|
||||
*
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
RCLookupHandler::init(
|
||||
std::shared_ptr<Contacts> c,
|
||||
std::shared_ptr<NodeDB> nodedb,
|
||||
EventLoop_ptr l,
|
||||
std::function<void(std::function<void()>)> dowork,
|
||||
LinkManager* linkManager,
|
||||
service::Context* hiddenServiceContext,
|
||||
const std::unordered_set<RouterID>& strictConnectPubkeys,
|
||||
const std::set<RemoteRC>& bootstrapRCList,
|
||||
bool isServiceNode_arg)
|
||||
{
|
||||
contacts = c;
|
||||
node_db = std::move(nodedb);
|
||||
loop = std::move(l);
|
||||
work_func = std::move(dowork);
|
||||
hidden_service_context = hiddenServiceContext;
|
||||
strict_connect_pubkeys = strictConnectPubkeys;
|
||||
bootstrap_rc_list = bootstrapRCList;
|
||||
link_manager = linkManager;
|
||||
router = &link_manager->router();
|
||||
isServiceNode = isServiceNode_arg;
|
||||
|
||||
for (const auto& rc : bootstrap_rc_list)
|
||||
{
|
||||
boostrap_rid_list.insert(rc.router_id());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RCLookupHandler::is_remote_in_bootstrap(const RouterID& remote) const
|
||||
{
|
||||
for (const auto& rc : bootstrap_rc_list)
|
||||
{
|
||||
if (rc.router_id() == remote)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
@ -1,143 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/util/thread/threading.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
struct llarp_dht_context;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
class NodeDB;
|
||||
struct Router;
|
||||
class EventLoop;
|
||||
|
||||
namespace service
|
||||
{
|
||||
struct Context;
|
||||
} // namespace service
|
||||
|
||||
struct Contacts;
|
||||
struct LinkManager;
|
||||
|
||||
enum class RCRequestResult
|
||||
{
|
||||
Success,
|
||||
InvalidRouter,
|
||||
RouterNotFound,
|
||||
BadRC
|
||||
};
|
||||
|
||||
using RCRequestCallback =
|
||||
std::function<void(const RouterID&, std::optional<RemoteRC>, bool success)>;
|
||||
|
||||
struct RCLookupHandler
|
||||
{
|
||||
public:
|
||||
~RCLookupHandler() = default;
|
||||
|
||||
void
|
||||
add_valid_router(const RouterID& router);
|
||||
|
||||
void
|
||||
remove_valid_router(const RouterID& router);
|
||||
|
||||
void
|
||||
set_router_whitelist(
|
||||
const std::vector<RouterID>& whitelist,
|
||||
const std::vector<RouterID>& greylist,
|
||||
const std::vector<RouterID>& greenlist);
|
||||
|
||||
bool
|
||||
has_received_whitelist() const;
|
||||
|
||||
void
|
||||
get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup = false);
|
||||
|
||||
bool
|
||||
is_path_allowed(const RouterID& remote) const;
|
||||
|
||||
bool
|
||||
is_session_allowed(const RouterID& remote) const;
|
||||
|
||||
bool
|
||||
is_grey_listed(const RouterID& remote) const;
|
||||
|
||||
// "greenlist" = new routers (i.e. "green") that aren't fully funded yet
|
||||
bool
|
||||
is_green_listed(const RouterID& remote) const;
|
||||
|
||||
// registered just means that there is at least an operator stake, but doesn't require the node
|
||||
// be fully funded, active, or not decommed. (In other words: it is any of the white, grey, or
|
||||
// green list).
|
||||
bool
|
||||
is_registered(const RouterID& remote) const;
|
||||
|
||||
bool
|
||||
check_rc(const RemoteRC& rc) const;
|
||||
|
||||
bool
|
||||
get_random_whitelist_router(RouterID& router) const;
|
||||
|
||||
void
|
||||
periodic_update(llarp_time_t now);
|
||||
|
||||
void
|
||||
explore_network();
|
||||
|
||||
size_t
|
||||
num_strict_connect_routers() const;
|
||||
|
||||
void
|
||||
init(
|
||||
std::shared_ptr<Contacts> contacts,
|
||||
std::shared_ptr<NodeDB> nodedb,
|
||||
std::shared_ptr<EventLoop> loop,
|
||||
std::function<void(std::function<void()>)> dowork,
|
||||
LinkManager* linkManager,
|
||||
service::Context* hiddenServiceContext,
|
||||
const std::unordered_set<RouterID>& strictConnectPubkeys,
|
||||
const std::set<RemoteRC>& bootstrapRCList,
|
||||
bool isServiceNode_arg);
|
||||
|
||||
std::unordered_set<RouterID>
|
||||
whitelist() const;
|
||||
|
||||
private:
|
||||
bool
|
||||
is_remote_in_bootstrap(const RouterID& remote) const;
|
||||
|
||||
std::shared_ptr<Contacts> contacts = nullptr;
|
||||
std::shared_ptr<NodeDB> node_db;
|
||||
std::shared_ptr<EventLoop> loop;
|
||||
std::function<void(std::function<void()>)> work_func = nullptr;
|
||||
service::Context* hidden_service_context = nullptr;
|
||||
LinkManager* link_manager = nullptr;
|
||||
Router* router;
|
||||
|
||||
/// explicit whitelist of routers we will connect to directly (not for
|
||||
/// service nodes)
|
||||
std::unordered_set<RouterID> strict_connect_pubkeys;
|
||||
|
||||
std::set<RemoteRC> bootstrap_rc_list;
|
||||
std::unordered_set<RouterID> boostrap_rid_list;
|
||||
|
||||
// Now that all calls are made through the event loop, any access to these
|
||||
// booleans is not guarded by a mutex
|
||||
std::atomic<bool> isServiceNode = false;
|
||||
|
||||
// whitelist = active routers
|
||||
std::unordered_set<RouterID> router_whitelist;
|
||||
// greylist = fully funded, but decommissioned routers
|
||||
std::unordered_set<RouterID> router_greylist;
|
||||
// greenlist = registered but not fully-staked routers
|
||||
std::unordered_set<RouterID> router_greenlist;
|
||||
};
|
||||
|
||||
} // namespace llarp
|
Loading…
Reference in New Issue