From cc1bcf86fab68f119f5df9eff62feeee26eb609d Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Tue, 27 Sep 2022 13:00:27 -0400 Subject: [PATCH] Fallback bootstrap router build parameter Adds a fallback bootstrap file path parameter to CMake, specify -DBOOTSTRAP_SYSTEM_PATH="/path/to/file" to use. Adds a list of (currently 1) obsolete bootstrap RouterIDs to check bootstrap RCs against. Will not use bootstrap RCs if they're on that list. Log an error periodically if we appear to be an active service node but have fewer than a set number (5) known peers. Bumps oxen-logging version for literal _format. --- CMakeLists.txt | 1 + llarp/CMakeLists.txt | 4 ++ llarp/bootstrap.cpp | 31 +++++++++++++ llarp/bootstrap.hpp | 4 ++ llarp/router/router.cpp | 99 ++++++++++++++++++++++++---------------- llarp/router_contact.cpp | 14 ++++++ llarp/router_contact.hpp | 3 ++ llarp/util/types.hpp | 3 ++ 8 files changed, 120 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c2145e5e..f66994b5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ set(RELEASE_MOTTO "Our Lord And Savior" CACHE STRING "Release motto") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") +set(BOOTSTRAP_SYSTEM_PATH "" CACHE PATH "Fallback bootstrap path") set(DEFAULT_WITH_BOOTSTRAP ON) if(APPLE) set(DEFAULT_WITH_BOOTSTRAP OFF) diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index d1d0196ef..b4a8cab18 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -235,6 +235,10 @@ add_library(lokinet-amalgum service/tag.cpp ) +if(BOOTSTRAP_SYSTEM_PATH) + message(STATUS "Building with fallback boostrap path \"${BOOTSTRAP_SYSTEM_PATH}\"") + target_compile_definitions(lokinet-amalgum PRIVATE "BOOTSTRAP_FALLBACK=\"${BOOTSTRAP_SYSTEM_PATH}\"") +endif() if(WITH_PEERSTATS_BACKEND) target_compile_definitions(lokinet-amalgum PRIVATE -DLOKINET_PEERSTATS_BACKEND) diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 56731257f..7d221ab66 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -36,4 +36,35 @@ namespace llarp { return BEncodeWriteList(begin(), end(), buf); } + + void + BootstrapList::AddFromFile(fs::path fpath) + { + bool isListFile = false; + { + std::ifstream inf(fpath.c_str(), std::ios::binary); + if (inf.is_open()) + { + const char ch = inf.get(); + isListFile = ch == 'l'; + } + } + if (isListFile) + { + if (not BDecodeReadFile(fpath, *this)) + { + throw std::runtime_error{fmt::format("failed to read bootstrap list file '{}'", fpath)}; + } + } + else + { + RouterContact rc; + if (not rc.Read(fpath)) + { + throw std::runtime_error{ + fmt::format("failed to decode bootstrap RC, file='{}', rc={}", fpath, rc)}; + } + this->insert(rc); + } + } } // namespace llarp diff --git a/llarp/bootstrap.hpp b/llarp/bootstrap.hpp index e9a62d7e9..ba126c03a 100644 --- a/llarp/bootstrap.hpp +++ b/llarp/bootstrap.hpp @@ -2,6 +2,7 @@ #include "router_contact.hpp" #include +#include "llarp/util/fs.hpp" namespace llarp { @@ -13,6 +14,9 @@ namespace llarp bool BEncode(llarp_buffer_t* buf) const; + void + AddFromFile(fs::path fpath); + void Clear(); }; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 421deb3f7..b1747dfdc 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -666,32 +666,7 @@ namespace llarp BootstrapList b_list; for (const auto& router : configRouters) { - bool isListFile = false; - { - std::ifstream inf(router.c_str(), std::ios::binary); - if (inf.is_open()) - { - const char ch = inf.get(); - isListFile = ch == 'l'; - } - } - if (isListFile) - { - if (not BDecodeReadFile(router, b_list)) - { - throw std::runtime_error{fmt::format("failed to read bootstrap list file '{}'", router)}; - } - } - else - { - RouterContact rc; - if (not rc.Read(router)) - { - throw std::runtime_error{ - fmt::format("failed to decode bootstrap RC, file='{}', rc={}", router, rc)}; - } - b_list.insert(rc); - } + b_list.AddFromFile(router); } for (const auto& rc : conf.bootstrap.routers) @@ -699,19 +674,52 @@ namespace llarp b_list.emplace(rc); } - for (auto& rc : b_list) + // in case someone has an old bootstrap file and is trying to use a bootstrap + // that no longer exists + for (auto rc_itr = b_list.begin(); rc_itr != b_list.end();) { - if (not rc.Verify(Now())) + if (rc_itr->IsObsoleteBootstrap()) + b_list.erase(rc_itr); + else + rc_itr++; + } + + auto verifyRCs = [&]() { + for (auto& rc : b_list) { - LogWarn("ignoring invalid RC: ", RouterID(rc.pubkey)); - continue; + if (rc.IsObsoleteBootstrap()) + { + LogWarn("ignoring obsolete boostrap RC: ", RouterID(rc.pubkey)); + continue; + } + if (not rc.Verify(Now())) + { + log::warning(logcat, "ignoring invalid RC: {}", RouterID(rc.pubkey)); + continue; + } + bootstrapRCList.emplace(std::move(rc)); } - bootstrapRCList.emplace(std::move(rc)); - } + }; + + verifyRCs(); + +#ifdef BOOTSTRAP_FALLBACK + constexpr std::string_view bootstrap_fallback = BOOTSTRAP_FALLBACK; +#else + constexpr std::string_view bootstrap_fallback{}; +#endif // BOOTSTRAP_FALLBACK if (bootstrapRCList.empty() and not conf.bootstrap.seednode) { - throw std::runtime_error{"we have no bootstrap nodes"}; + if (not bootstrap_fallback.empty()) + { + b_list.clear(); + b_list.AddFromFile(bootstrap_fallback); + + verifyRCs(); + } + if (bootstrapRCList.empty()) // empty after trying fallback, if set + throw std::runtime_error{"we have no bootstrap nodes"}; } if (conf.bootstrap.seednode) @@ -1038,14 +1046,27 @@ namespace llarp connectToNum = strictConnect; } - if (auto dereg = LooksDeregistered(); (dereg or decom) and now >= m_NextDecommissionWarn) + if (now >= m_NextDecommissionWarn) { - // complain about being deregistered constexpr auto DecommissionWarnInterval = 5min; - LogError( - "We are running as a service node but we seem to be ", - dereg ? "deregistered" : "decommissioned"); - m_NextDecommissionWarn = now + DecommissionWarnInterval; + if (auto dereg = LooksDeregistered(); dereg or decom) + { + // complain about being deregistered + LogError( + "We are running as a service node but we seem to be ", + dereg ? "deregistered" : "decommissioned"); + m_NextDecommissionWarn = now + DecommissionWarnInterval; + } + else if (isSvcNode) + { + constexpr int KnownPeerWarningThreshold = 5; + if (nodedb()->NumLoaded() < KnownPeerWarningThreshold) + log::error( + logcat, + "We appear to be an active service node, but have fewer than {} known peers.", + KnownPeerWarningThreshold); + m_NextDecommissionWarn = now + DecommissionWarnInterval; + } } // if we need more sessions to routers and we are not a service node kicked from the network diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 598aa1753..9004c1c34 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -533,6 +533,20 @@ namespace llarp return false; } + static constexpr std::array obsolete_bootstraps = { + "7a16ac0b85290bcf69b2f3b52456d7e989ac8913b4afbb980614e249a3723218"sv}; + + bool + RouterContact::IsObsoleteBootstrap() const + { + for (const auto& k : obsolete_bootstraps) + { + if (pubkey.ToHex() == k) + return true; + } + return false; + } + bool RouterContact::Write(const fs::path& fname) const { diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index bafade89b..340bab597 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -205,6 +205,9 @@ namespace llarp bool FromOurNetwork() const; + bool + IsObsoleteBootstrap() const; + private: bool DecodeVersion_0(llarp_buffer_t* buf); diff --git a/llarp/util/types.hpp b/llarp/util/types.hpp index be6a0a286..1944bd905 100644 --- a/llarp/util/types.hpp +++ b/llarp/util/types.hpp @@ -3,6 +3,8 @@ #include #include +#include "oxen/log/format.hpp" + using byte_t = uint8_t; using llarp_proto_version_t = std::uint8_t; @@ -10,6 +12,7 @@ namespace llarp { using Duration_t = std::chrono::milliseconds; using namespace std::literals; + using namespace oxen::log::literals; /// convert to milliseconds uint64_t