diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index e7e06d0fe..657c20cb2 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -24,7 +24,6 @@ lokinet_add_library(lokinet-core-utils exit/policy.cpp # net/ handlers/exit.cpp # link/ exit/ handlers/tun.cpp - router/rc_gossiper.cpp service/auth.cpp # config/ service/context.cpp service/identity.cpp diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp deleted file mode 100644 index a5da35bd3..000000000 --- a/llarp/router/rc_gossiper.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "rc_gossiper.hpp" - -#include -#include - -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(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 - 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 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 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(m_router->pubkey(), rc); - - // send message - peerSession->SendMessageBuffer(std::move(msg), nullptr, gossip.Priority()); - }); - * - * - */ - - return true; - } - -} // namespace llarp diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp deleted file mode 100644 index a0c72fc80..000000000 --- a/llarp/router/rc_gossiper.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include -#include - -#include - -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 - LastGossipAt() const; - - private: - RouterID rid; - Time_t last_rc_gossip = 0s; - LinkManager* link_manager = nullptr; - util::DecayingHashSet filter; - - Router* router; - }; -} // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 9ef2972cb..6c5e04b59 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -227,20 +227,6 @@ namespace llarp _link_manager.set_conn_persist(remote, until); } - void - Router::GossipRCIfNeeded(const LocalRC rc) - { - /// if we are not a service node forget about gossip - if (not is_service_node()) - return; - /// wait for random uptime - if (std::chrono::milliseconds{Uptime()} < _randomStartDelay) - return; - auto view = rc.view(); - _link_manager.gossip_rc( - pubkey(), std::string{reinterpret_cast(view.data()), view.size()}); - } - std::optional Router::GetRandomGoodRouter() { @@ -533,16 +519,6 @@ namespace llarp queue_disk_io([&]() { router_contact.write(our_rc_file); }); } - bool - Router::update_rc() - { - router_contact.resign(); - if (is_service_node()) - save_rc(); - - return true; - } - bool Router::from_config(const Config& conf) { @@ -779,12 +755,12 @@ namespace llarp " | {} active paths | block {} ", path_context().CurrentTransitPaths(), (_rpc_client ? _rpc_client->BlockHeight() : 0)); - auto maybe_last = _rcGossiper.LastGossipAt(); + bool have_gossiped = last_rc_gossip == std::chrono::system_clock::time_point::min(); fmt::format_to( out, " | gossip: (next/last) {} / {}", - short_time_from_now(_rcGossiper.NextGossipAt()), - maybe_last ? short_time_from_now(*maybe_last) : "never"); + short_time_from_now(next_rc_gossip), + have_gossiped ? short_time_from_now(last_rc_gossip) : "never"); } else { @@ -837,33 +813,28 @@ namespace llarp report_stats(); } - _rcGossiper.Decay(now); - const bool is_snode = is_service_node(); const bool is_decommed = appears_decommed(); - bool should_gossip = appears_funded(); - if (is_snode - and (router_contact.expires_within_delta(now, std::chrono::milliseconds(randint() % 10000)) - or (now - router_contact.timestamp().time_since_epoch()) > rc_regen_interval)) + // (relay-only) if we have fetched the relay list from oxend and + // we are registered and funded, we want to gossip our RC periodically + auto now_timepoint = std::chrono::system_clock::time_point(now); + if (is_snode and appears_funded() and (now_timepoint > next_rc_gossip)) { - LogInfo("regenerating RC"); - if (update_rc()) - { - // our rc changed so we should gossip it - should_gossip = true; - // remove our replay entry so it goes out - _rcGossiper.Forget(pubkey()); - } - else - LogError("failed to update our RC"); - } - if (should_gossip) - { - // if we have the whitelist enabled, we have fetched the list and we are in either - // the white or grey list, we want to gossip our RC - GossipRCIfNeeded(router_contact); + log::info(logcat, "regenerating and gossiping RC"); + router_contact.resign(); + save_rc(); + auto view = router_contact.view(); + _link_manager.gossip_rc( + pubkey(), std::string{reinterpret_cast(view.data()), view.size()}); + last_rc_gossip = now_timepoint; + + // 1min to 5min before "stale time" is next gossip time + auto random_delta = + std::chrono::seconds{std::uniform_int_distribution{60, 300}(llarp::csrng)}; + next_rc_gossip = now_timepoint + RouterContact::STALE_AGE - random_delta; } + // remove RCs for nodes that are no longer allowed by network policy node_db()->RemoveIf([&](const RemoteRC& rc) -> bool { // don't purge bootstrap nodes from nodedb @@ -1052,7 +1023,6 @@ namespace llarp log::info(logcat, "Router initialized as service node!"); const RouterID us = pubkey(); - _rcGossiper.Init(&_link_manager, us, this); // relays do not use profiling router_profiling().Disable(); } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 811a27af7..faf8908fc 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -1,6 +1,5 @@ #pragma once -#include "rc_gossiper.hpp" #include "route_poker.hpp" #include @@ -125,11 +124,10 @@ namespace llarp Profiling _router_profiling; fs::path _profile_file; LinkManager _link_manager{*this}; - RCGossiper _rcGossiper; - - /// how often do we resign our RC? milliseconds. - // TODO: make configurable - llarp_time_t rc_regen_interval = 1h; + std::chrono::system_clock::time_point last_rc_gossip{ + std::chrono::system_clock::time_point::min()}; + std::chrono::system_clock::time_point next_rc_gossip{ + std::chrono::system_clock::time_point::min()}; // should we be sending padded messages every interval? bool send_padding = false; @@ -147,9 +145,6 @@ namespace llarp void save_rc(); - bool - update_rc(); - bool from_config(const Config& conf); @@ -365,9 +360,6 @@ namespace llarp std::string status_line(); - void - GossipRCIfNeeded(const LocalRC rc); - void InitInboundLinks(); diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 49aa96cce..b65aa2c76 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -56,19 +56,18 @@ namespace llarp /// Timespans for RCs: - /// How long (relative to its timestamp) before an RC becomes stale. Stale records are used - /// (e.g. for path building) only if there are no non-stale records available, such as might be + /// How long (from its signing time) before an RC is considered "stale". Relays republish + /// their RCs slightly more frequently than this so that ideally this won't happen. + static constexpr auto STALE_AGE = 6h; + + /// How long (from its signing time) before an RC becomes "outdated". Outdated records are used + /// (e.g. for path building) only if there are no newer records available, such as might be /// the case when a client has been turned off for a while. - static constexpr auto STALE = 12h; + static constexpr auto OUTDATED_AGE = 12h; /// How long before an RC becomes invalid (and thus deleted). static constexpr auto LIFETIME = 30 * 24h; - /// How long before a relay updates and re-publish its RC to the network. (Relays can - /// re-publish more frequently than this if needed; this is meant to apply only if there are no - /// changes i.e. just to push out a new confirmation of the details). - static constexpr auto REPUBLISH = STALE / 2 - 5min; - ustring_view view() const {