diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 8d1dd9e35..e7e06d0fe 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -109,7 +109,6 @@ lokinet_add_library(lokinet-time-place # lokinet-platform holds all platform specific code lokinet_add_library(lokinet-platform net/interface_info.cpp - router/rc_lookup_handler.cpp vpn/packet_router.cpp vpn/platform.cpp ) diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 64f07d001..ffab0a37c 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -2,8 +2,8 @@ #include #include +#include #include -#include #include #include @@ -243,9 +243,8 @@ namespace llarp::handlers { if (msg.questions[0].IsName("random.snode")) { - RouterID random; - if (GetRouter()->GetRandomGoodRouter(random)) - msg.AddCNAMEReply(random.ToString(), 1); + if (auto random = GetRouter()->GetRandomGoodRouter()) + msg.AddCNAMEReply(random->ToString(), 1); else msg.AddNXReply(); } @@ -263,11 +262,10 @@ namespace llarp::handlers const bool isV4 = msg.questions[0].qtype == dns::qTypeA; if (msg.questions[0].IsName("random.snode")) { - RouterID random; - if (GetRouter()->GetRandomGoodRouter(random)) + if (auto random = GetRouter()->GetRandomGoodRouter()) { - msg.AddCNAMEReply(random.ToString(), 1); - auto ip = ObtainServiceNodeIP(random); + msg.AddCNAMEReply(random->ToString(), 1); + auto ip = ObtainServiceNodeIP(*random); msg.AddINReply(ip, false); } else @@ -333,7 +331,7 @@ namespace llarp::handlers void ExitEndpoint::ObtainSNodeSession(const RouterID& rid, exit::SessionReadyFunc obtain_cb) { - if (not router->rc_lookup_handler().is_session_allowed(rid)) + if (not router->node_db()->is_connection_allowed(rid)) { obtain_cb(nullptr); return; diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index ad288017b..fec8b8187 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -705,10 +705,9 @@ namespace llarp::handlers { if (is_random_snode(msg)) { - RouterID random; - if (router()->GetRandomGoodRouter(random)) + if (auto random = router()->GetRandomGoodRouter()) { - msg.AddCNAMEReply(random.ToString(), 1); + msg.AddCNAMEReply(random->ToString(), 1); } else msg.AddNXReply(); @@ -755,11 +754,10 @@ namespace llarp::handlers // on MacOS this is a typeA query else if (is_random_snode(msg)) { - RouterID random; - if (router()->GetRandomGoodRouter(random)) + if (auto random = router()->GetRandomGoodRouter()) { - msg.AddCNAMEReply(random.ToString(), 1); - return ReplyToSNodeDNSWhenReady(random, std::make_shared(msg), isV6); + msg.AddCNAMEReply(random->ToString(), 1); + return ReplyToSNodeDNSWhenReady(*random, std::make_shared(msg), isV6); } msg.AddNXReply(); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 6c6a10c48..175f85ee3 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -243,21 +242,17 @@ namespace llarp return true; } - _router.loop()->call([this, remote, endpoint, body, f = std::move(func)]() { - auto pending = PendingControlMessage(body, endpoint, f); + _router.loop()->call([this, + remote, + endpoint = std::move(endpoint), + body = std::move(body), + f = std::move(func)]() { + auto pending = PendingControlMessage(std::move(body), std::move(endpoint), f); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); itr->second.push_back(std::move(pending)); - rc_lookup->get_rc(remote, [this]([[maybe_unused]] auto rid, auto rc, auto success) { - if (success) - { - _router.node_db()->put_rc_if_newer(*rc); - connect_to(*rc); - } - else - log::warning(quic_cat, "Do something intelligent here for error handling"); - }); + connect_to(remote); }); return false; @@ -275,21 +270,13 @@ namespace llarp return true; } - _router.loop()->call([&]() { + _router.loop()->call([this, body = std::move(body), remote]() { auto pending = PendingDataMessage(body); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); itr->second.push_back(std::move(pending)); - rc_lookup->get_rc(remote, [this]([[maybe_unused]] auto rid, auto rc, auto success) { - if (success) - { - _router.node_db()->put_rc_if_newer(*rc); - connect_to(*rc); - } - else - log::warning(quic_cat, "Do something intelligent here for error handling"); - }); + connect_to(remote); }); return false; @@ -304,15 +291,13 @@ namespace llarp void LinkManager::connect_to(const RouterID& rid) { - rc_lookup->get_rc(rid, [this]([[maybe_unused]] auto rid, auto rc, auto success) { - if (success) - { - _router.node_db()->put_rc_if_newer(*rc); - connect_to(*rc); - } - else - log::warning(quic_cat, "Do something intelligent here for error handling"); - }); + auto rc = node_db->get_rc(rid); + if (rc) + { + connect_to(*rc); + } + else + log::warning(quic_cat, "Do something intelligent here for error handling"); } // This function assumes the RC has already had its signature verified and connection is allowed. @@ -400,6 +385,27 @@ namespace llarp }); } + void + LinkManager::gossip_rc(const RemoteRC& rc) + { + for (auto& [rid, conn] : ep.conns) + send_control_message(rid, "gossip_rc", std::string{rc.view()}, nullptr); + } + + void + LinkManager::handle_gossip_rc(oxen::quic::message m) + { + try + { + RemoteRC rc{m.body()}; + } + catch (const std::exception& e) + { + log::info(link_cat, "Recieved invalid RC, dropping on the floor."); + return; + } + } + bool LinkManager::have_connection_to(const RouterID& remote, bool client_only) const { @@ -486,10 +492,9 @@ namespace llarp } void - LinkManager::init(RCLookupHandler* rcLookup) + LinkManager::init() { is_stopping = false; - rc_lookup = rcLookup; node_db = _router.node_db(); } @@ -509,7 +514,7 @@ namespace llarp { exclude.insert(maybe_other->router_id()); - if (not rc_lookup->is_session_allowed(maybe_other->router_id())) + if (not node_db->is_connection_allowed(maybe_other->router_id())) continue; connect_to(*maybe_other); @@ -630,8 +635,9 @@ namespace llarp { std::string neighbors{}; - const auto closest_rcs = - _router.node_db()->find_many_closest_to(target_addr, RC_LOOKUP_STORAGE_REDUNDANCY); + // TODO: constant replaced with 4 (what the constant it referred to was) for compilation, + // pending removal + const auto closest_rcs = _router.node_db()->find_many_closest_to(target_addr, 4); for (const auto& rc : closest_rcs) { diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 1f05c8c3b..4efda035a 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -27,6 +26,7 @@ namespace namespace llarp { struct LinkManager; + struct NodeDB; namespace link { @@ -176,7 +176,6 @@ namespace llarp util::DecayingHashSet clients{path::DEFAULT_LIFETIME}; - RCLookupHandler* rc_lookup; std::shared_ptr node_db; oxen::quic::Address addr; @@ -221,6 +220,12 @@ namespace llarp return addr; } + void + gossip_rc(const RemoteRC& rc); + + void + handle_gossip_rc(oxen::quic::message m); + bool have_connection_to(const RouterID& remote, bool client_only = false) const; @@ -261,7 +266,7 @@ namespace llarp extract_status() const; void - init(RCLookupHandler* rcLookup); + init(); void for_each_connection(std::function func); diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index a5955003d..7207a2b0d 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -99,6 +99,73 @@ namespace llarp return m_Root / skiplistDir / fname; } + void + NodeDB::set_bootstrap_routers(const std::set& rcs) + { + bootstraps.clear(); // this function really shouldn't be called more than once, but... + for (const auto& rc : rcs) + bootstraps.emplace(rc.router_id(), rc); + } + + void + NodeDB::set_router_whitelist( + const std::vector& whitelist, + const std::vector& greylist, + const std::vector& greenlist) + { + if (whitelist.empty()) + return; + + registered_routers.clear(); + registered_routers.insert(whitelist.begin(), whitelist.end()); + registered_routers.insert(greylist.begin(), greylist.end()); + registered_routers.insert(greenlist.begin(), greenlist.end()); + + router_whitelist.clear(); + router_whitelist.insert(whitelist.begin(), whitelist.end()); + router_greylist.clear(); + router_greylist.insert(greylist.begin(), greylist.end()); + router_greenlist.clear(); + router_greenlist.insert(greenlist.begin(), greenlist.end()); + + log::info( + logcat, "lokinet service node list now has ", router_whitelist.size(), " active routers"); + } + + std::optional + NodeDB::get_random_whitelist_router() const + { + const auto sz = router_whitelist.size(); + if (sz == 0) + return std::nullopt; + auto itr = router_whitelist.begin(); + if (sz > 1) + std::advance(itr, randint() % sz); + return *itr; + } + + bool + NodeDB::is_connection_allowed(const RouterID& remote) const + { + if (pinned_edges.size() && pinned_edges.count(remote) == 0 && !bootstraps.count(remote)) + { + return false; + } + + if (not router.is_service_node()) + return true; + + return router_whitelist.count(remote) or router_greylist.count(remote); + } + + bool + NodeDB::is_first_hop_allowed(const RouterID& remote) const + { + if (pinned_edges.size() && pinned_edges.count(remote) == 0) + return false; + return true; + } + void NodeDB::load_from_disk() { @@ -180,14 +247,12 @@ namespace llarp std::optional NodeDB::get_rc(RouterID pk) const { - return router.loop()->call_get([this, pk]() -> std::optional { - const auto itr = entries.find(pk); + const auto itr = entries.find(pk); - if (itr == entries.end()) - return std::nullopt; + if (itr == entries.end()) + return std::nullopt; - return itr->second.rc; - }); + return itr->second.rc; } void diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 7552fc6fd..7d7c088eb 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -49,7 +49,85 @@ namespace llarp fs::path get_path_by_pubkey(RouterID pk) const; + std::unordered_map bootstraps; + + // whitelist = active routers + std::unordered_set router_whitelist; + // greylist = fully funded, but decommissioned routers + std::unordered_set router_greylist; + // greenlist = registered but not fully-staked routers + std::unordered_set router_greenlist; + + // all registered relays (snodes) + std::unordered_set registered_routers; + + // only ever use to specific edges as path first-hops + std::unordered_set pinned_edges; + public: + void + set_bootstrap_routers(const std::set& rcs); + + const std::unordered_set& + whitelist() const + { + return router_whitelist; + } + + const std::unordered_set& + greylist() const + { + return router_greylist; + } + + const std::unordered_set& + get_registered_routers() const + { + return registered_routers; + } + + void + set_router_whitelist( + const std::vector& whitelist, + const std::vector& greylist, + const std::vector& greenlist); + + std::optional + get_random_whitelist_router() const; + + // client: + // if pinned edges were specified, connections are allowed only to those and + // to the configured bootstrap nodes. otherwise, always allow. + // + // relay: + // outgoing connections are allowed only to other registered, funded relays + // (whitelist and greylist, respectively). + bool + is_connection_allowed(const RouterID& remote) const; + + // client: + // same as is_connection_allowed + // + // server: + // we only build new paths through registered, not decommissioned relays + // (i.e. whitelist) + bool + is_path_allowed(const RouterID& remote) const + { + return router_whitelist.count(remote); + } + + // if pinned edges were specified, the remote must be in that set, else any remote + // is allowed as first hop. + bool + is_first_hop_allowed(const RouterID& remote) const; + + const std::unordered_set& + get_pinned_edges() const + { + return pinned_edges; + } + explicit NodeDB( fs::path rootdir, std::function)> diskCaller, Router* r); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 2f51e5fae..49b080cd0 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -575,30 +574,6 @@ namespace llarp router->router_profiling().MarkPathTimeout(p.get()); PathSet::HandlePathBuildTimeout(p); DoPathBuildBackoff(); - for (const auto& hop : p->hops) - { - const auto& target = hop.rc.router_id(); - // look up router and see if it's still on the network - log::info(path_cat, "Looking up RouterID {} due to path build timeout", target); - - router->rc_lookup_handler().get_rc( - target, - [this](auto rid, auto rc, auto success) { - if (success && rc) - { - log::info(path_cat, "Refreshed RouterContact for {}", rid); - router->node_db()->put_rc_if_newer(*rc); - } - else - { - // remove all connections to this router as it's probably not registered anymore - log::warning(path_cat, "Removing router {} due to path build timeout", rid); - router->link_manager().deregister_peer(rid); - router->node_db()->remove_router(rid); - } - }, - true); - } } void diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp deleted file mode 100644 index c2df0c833..000000000 --- a/llarp/router/rc_lookup_handler.cpp +++ /dev/null @@ -1,357 +0,0 @@ -#include "rc_lookup_handler.hpp" - -#include "router.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -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& beigelist, const std::vector& new_beige) - { - beigelist.clear(); - beigelist.insert(new_beige.begin(), new_beige.end()); - } - - void - RCLookupHandler::set_router_whitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& 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 - 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 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 lookup_routers = router->loop()->call_get([this]() { - std::vector 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 c, - std::shared_ptr nodedb, - EventLoop_ptr l, - std::function)> dowork, - LinkManager* linkManager, - service::Context* hiddenServiceContext, - const std::unordered_set& strictConnectPubkeys, - const std::set& 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 diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp deleted file mode 100644 index f7b3f01f4..000000000 --- a/llarp/router/rc_lookup_handler.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include - -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, 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& whitelist, - const std::vector& greylist, - const std::vector& 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, - std::shared_ptr nodedb, - std::shared_ptr loop, - std::function)> dowork, - LinkManager* linkManager, - service::Context* hiddenServiceContext, - const std::unordered_set& strictConnectPubkeys, - const std::set& bootstrapRCList, - bool isServiceNode_arg); - - std::unordered_set - whitelist() const; - - private: - bool - is_remote_in_bootstrap(const RouterID& remote) const; - - std::shared_ptr contacts = nullptr; - std::shared_ptr node_db; - std::shared_ptr loop; - std::function)> 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 strict_connect_pubkeys; - - std::set bootstrap_rc_list; - std::unordered_set 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 isServiceNode = false; - - // whitelist = active routers - std::unordered_set router_whitelist; - // greylist = fully funded, but decommissioned routers - std::unordered_set router_greylist; - // greenlist = registered but not fully-staked routers - std::unordered_set router_greenlist; - }; - -} // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 6c4f51eac..56c1787cc 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -239,20 +239,19 @@ namespace llarp _rcGossiper.GossipRC(rc); } - bool - Router::GetRandomGoodRouter(RouterID& router) + std::optional + Router::GetRandomGoodRouter() { if (is_service_node()) { - return _rc_lookup_handler.get_random_whitelist_router(router); + return node_db()->get_random_whitelist_router(); } if (auto maybe = node_db()->GetRandom([](const auto&) -> bool { return true; })) { - router = maybe->router_id(); - return true; + return maybe->router_id(); } - return false; + return std::nullopt; } void @@ -479,25 +478,25 @@ namespace llarp bool Router::have_snode_whitelist() const { - return is_service_node() and _rc_lookup_handler.has_received_whitelist(); + return whitelist_received; } bool Router::appears_decommed() const { - return have_snode_whitelist() and _rc_lookup_handler.is_grey_listed(pubkey()); + return have_snode_whitelist() and node_db()->greylist().count(pubkey()); } bool Router::appears_funded() const { - return have_snode_whitelist() and _rc_lookup_handler.is_session_allowed(pubkey()); + return have_snode_whitelist() and node_db()->is_connection_allowed(pubkey()); } bool Router::appears_registered() const { - return have_snode_whitelist() and _rc_lookup_handler.is_registered(pubkey()); + return have_snode_whitelist() and node_db()->get_registered_routers().count(pubkey()); } bool @@ -509,7 +508,7 @@ namespace llarp bool Router::SessionToRouterAllowed(const RouterID& router) const { - return _rc_lookup_handler.is_session_allowed(router); + return node_db()->is_connection_allowed(router); } bool @@ -520,7 +519,7 @@ namespace llarp // we are decom'd don't allow any paths outbound at all return false; } - return _rc_lookup_handler.is_path_allowed(router); + return node_db()->is_path_allowed(router); } size_t @@ -679,23 +678,15 @@ namespace llarp it = bootstrap_rc_list.erase(it); } + node_db()->set_bootstrap_routers(bootstrap_rc_list); + if (conf.bootstrap.seednode) LogInfo("we are a seed node"); else LogInfo("Loaded ", bootstrap_rc_list.size(), " bootstrap routers"); // Init components after relevant config settings loaded - _link_manager.init(&_rc_lookup_handler); - _rc_lookup_handler.init( - _contacts, - _node_db, - _loop, - [this](std::function work) { queue_work(std::move(work)); }, - &_link_manager, - &_hidden_service_context, - strictConnectPubkeys, - bootstrap_rc_list, - _is_service_node); + _link_manager.init(); // FIXME: kludge for now, will be part of larger cleanup effort. if (_is_service_node) @@ -856,9 +847,6 @@ namespace llarp _rcGossiper.Decay(now); - _rc_lookup_handler.periodic_update(now); - - const bool has_whitelist = _rc_lookup_handler.has_received_whitelist(); const bool is_snode = is_service_node(); const bool is_decommed = appears_decommed(); bool should_gossip = appears_funded(); @@ -915,7 +903,7 @@ namespace llarp } // if we don't have the whitelist yet don't remove the entry - if (not has_whitelist) + if (not whitelist_received) { log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.router_id()); return false; @@ -924,7 +912,7 @@ namespace llarp // the whitelist enabled and we got the whitelist // check against the whitelist and remove if it's not // in the whitelist OR if there is no whitelist don't remove - if (has_whitelist and not _rc_lookup_handler.is_session_allowed(rc.router_id())) + if (not node_db()->is_connection_allowed(rc.router_id())) { log::debug(logcat, "Removing {}: not a valid router", rc.router_id()); return true; @@ -932,7 +920,9 @@ namespace llarp return false; }); - if (not is_snode or not has_whitelist) + /* TODO: this behavior seems incorrect, but fixing it will require discussion + * + if (not is_snode or not whitelist_received) { // find all deregistered relays std::unordered_set close_peers; @@ -948,23 +938,18 @@ namespace llarp for (auto& peer : close_peers) _link_manager.deregister_peer(peer); } + */ _link_manager.check_persisting_conns(now); size_t connected = NumberOfConnectedRouters(); - const int interval = is_snode ? 5 : 2; - const auto timepoint_now = std::chrono::steady_clock::now(); - if (timepoint_now >= _next_explore_at and not is_decommed) - { - _rc_lookup_handler.explore_network(); - _next_explore_at = timepoint_now + std::chrono::seconds(interval); - } size_t connectToNum = _link_manager.min_connected_routers; - const auto strictConnect = _rc_lookup_handler.num_strict_connect_routers(); - if (strictConnect > 0 && connectToNum > strictConnect) + const auto& pinned_edges = _node_db->get_pinned_edges(); + const auto pinned_count = pinned_edges.size(); + if (pinned_count > 0 && connectToNum > pinned_count) { - connectToNum = strictConnect; + connectToNum = pinned_count; } if (is_snode and now >= _next_decomm_warning) @@ -1032,13 +1017,20 @@ namespace llarp return _link_manager.get_random_connected(result); } + std::unordered_set + Router::router_whitelist() const + { + return _node_db->whitelist(); + } + void Router::set_router_whitelist( const std::vector& whitelist, const std::vector& greylist, const std::vector& unfundedlist) { - _rc_lookup_handler.set_router_whitelist(whitelist, greylist, unfundedlist); + node_db()->set_router_whitelist(whitelist, greylist, unfundedlist); + whitelist_received = true; } bool diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 9a2973477..92b412acd 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -1,7 +1,6 @@ #pragma once #include "rc_gossiper.hpp" -#include "rc_lookup_handler.hpp" #include "route_poker.hpp" #include @@ -59,8 +58,6 @@ namespace llarp static constexpr size_t INTROSET_STORAGE_REDUNDANCY = (INTROSET_RELAY_REDUNDANCY * INTROSET_REQS_PER_RELAY); - static constexpr size_t RC_LOOKUP_STORAGE_REDUNDANCY{4}; - struct Contacts; struct Router : std::enable_shared_from_this @@ -122,12 +119,12 @@ namespace llarp const llarp_time_t _randomStartDelay; std::shared_ptr _rpc_client; + bool whitelist_received{false}; oxenmq::address rpc_addr; Profiling _router_profiling; fs::path _profile_file; LinkManager _link_manager{*this}; - RCLookupHandler _rc_lookup_handler; RCGossiper _rcGossiper; /// how often do we resign our RC? milliseconds. @@ -211,12 +208,6 @@ namespace llarp return _link_manager; } - RCLookupHandler& - rc_lookup_handler() - { - return _rc_lookup_handler; - } - inline int outbound_udp_socket() const { @@ -293,10 +284,7 @@ namespace llarp ExtractSummaryStatus() const; std::unordered_set - router_whitelist() const - { - return _rc_lookup_handler.whitelist(); - } + router_whitelist() const; void set_router_whitelist( @@ -389,8 +377,8 @@ namespace llarp void InitOutboundLinks(); - bool - GetRandomGoodRouter(RouterID& r); + std::optional + GetRandomGoodRouter(); /// initialize us as a service node /// return true on success