Compare commits

...

7 Commits

Author SHA1 Message Date
dr7ana 63c9bd6e63 update seeds before returning no 2023-12-12 10:24:31 -08:00
dr7ana eb971265c7 wrap dat 2023-12-12 10:19:56 -08:00
Jason Rhinelander b0d6d0cc2b
Bump libquic for register_command fix 2023-12-12 14:05:50 -04:00
Jason Rhinelander 4c7f9d080f
Replace GetBestNetIF with quic::Address version
It is now called get_best_public_address, and takes (bool, port)
argument to return an optional quic::Address to make life easier: the
caller now can just give the default port to set, and we keep the C
sockaddr* more constrained.
2023-12-12 14:05:50 -04:00
dr7ana 6cb2f57abd whatever 2023-12-12 09:44:59 -08:00
dr7ana b69f754599 come on already work already 2023-12-12 08:11:34 -08:00
dr7ana 94f307283f libquic vbump 2023-12-12 05:43:28 -08:00
15 changed files with 181 additions and 133 deletions

@ -1 +1 @@
Subproject commit ad8904debc55f9495667e8571ee5bb963156d54e
Subproject commit 3ace46701449c4c01f74aae2e0be3b4164768911

View File

@ -26,7 +26,7 @@ namespace llarp
}
bool
BootstrapList::contains(const RouterID& rid)
BootstrapList::contains(const RouterID& rid) const
{
for (const auto& it : *this)
{
@ -38,7 +38,7 @@ namespace llarp
}
bool
BootstrapList::contains(const RemoteRC& rc)
BootstrapList::contains(const RemoteRC& rc) const
{
return count(rc);
}

View File

@ -12,7 +12,7 @@ namespace llarp
{
struct BootstrapList final : public std::set<RemoteRC>
{
std::set<RemoteRC>::iterator _curr;
std::set<RemoteRC>::iterator _curr = begin();
const RemoteRC&
current()
@ -30,13 +30,16 @@ namespace llarp
read_from_file(const fs::path& fpath);
bool
contains(const RouterID& rid);
contains(const RouterID& rid) const;
// returns a reference to the next index and a boolean that equals true if
// this is the front of the set
const RemoteRC&
next()
{
if (size() < 2)
return *_curr;
++_curr;
if (_curr == this->end())
@ -46,7 +49,7 @@ namespace llarp
}
bool
contains(const RemoteRC& rc);
contains(const RemoteRC& rc) const;
void
randomize()

View File

@ -961,14 +961,10 @@ namespace llarp
throw std::invalid_argument{fmt::format("{} is a loopback address", arg)};
}
if (not maybe)
{
// infer public address
if (auto maybe_ifname = net_ptr->GetBestNetIF())
maybe = oxen::quic::Address{*maybe_ifname};
}
if (maybe && maybe->port() == 0)
maybe = oxen::quic::Address{maybe->host(), DEFAULT_LISTEN_PORT};
maybe = net_ptr->get_best_public_address(true, DEFAULT_LISTEN_PORT);
else if (maybe && maybe->port() == 0)
maybe->set_port(DEFAULT_LISTEN_PORT);
return maybe;
};

View File

@ -178,12 +178,13 @@ namespace llarp
bool result = false;
RouterID other{key.data()};
if (auto itr = rids_pending_verification.find(other); itr != rids_pending_verification.end())
{
verified_rids[other] = itr->second;
rids_pending_verification.erase(itr);
result = true;
}
// if (auto itr = rids_pending_verification.find(other); itr !=
// rids_pending_verification.end())
// {
// verified_rids[other] = itr->second;
// rids_pending_verification.erase(itr);
// result = true;
// }
if (_router.node_db()->has_rc(other))
result = true;
@ -254,7 +255,8 @@ namespace llarp
if (func)
{
func = [this, f = std::move(func)](oxen::quic::message m) mutable {
_router.loop()->call([func = std::move(f), msg = std::move(m)]() mutable { func(std::move(msg)); });
_router.loop()->call(
[func = std::move(f), msg = std::move(m)]() mutable { func(std::move(msg)); });
};
}
@ -350,6 +352,7 @@ namespace llarp
{
if (auto conn = ep.get_conn(rc.router_id()); conn)
{
log::error(logcat, "We should not be here!");
// TODO: should implement some connection failed logic, but not the same logic that
// would be executed for another failure case
return;
@ -358,12 +361,12 @@ namespace llarp
const auto& remote_addr = rc.addr();
const auto& rid = rc.router_id();
rids_pending_verification[rid] = rc;
// rids_pending_verification[rid] = rc;
// TODO: confirm remote end is using the expected pubkey (RouterID).
// TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation)
if (auto rv = ep.establish_connection(
oxen::quic::RemoteAddress{rc.router_id().ToView(), remote_addr},
oxen::quic::RemoteAddress{rid.ToView(), remote_addr},
rc,
std::move(on_open),
std::move(on_close));
@ -391,6 +394,7 @@ namespace llarp
logcat, "BTRequestStream closed unexpectedly (ec:{}); closing connection...", error_code);
s.conn.close_connection(error_code);
});
register_commands(control_stream);
itr->second = std::make_shared<link::Connection>(ci.shared_from_this(), control_stream, rc);
log::critical(logcat, "Successfully configured inbound connection fom {}; storing RC...", rid);
@ -460,9 +464,10 @@ namespace llarp
{
const auto& rid = c_itr->second;
if (auto maybe = rids_pending_verification.find(rid);
maybe != rids_pending_verification.end())
rids_pending_verification.erase(maybe);
// if (auto maybe = rids_pending_verification.find(rid);
// maybe != rids_pending_verification.end())
// rids_pending_verification.erase(maybe);
// in case this didn't clear earlier, do it now
if (auto p_itr = pending_conn_msg_queue.find(rid); p_itr != pending_conn_msg_queue.end())
pending_conn_msg_queue.erase(p_itr);
@ -621,16 +626,26 @@ namespace llarp
LinkManager::fetch_bootstrap_rcs(
const RemoteRC& source, std::string payload, std::function<void(oxen::quic::message m)> func)
{
_router.loop()->call([this, source, payload, f = std::move(func)]() {
_router.loop()->call([this, source, payload, f = std::move(func)]() mutable {
if (f)
{
f = [this, func = std::move(f)](oxen::quic::message m) mutable {
_router.loop()->call([f = std::move(func), msg = std::move(m)]() mutable {
f(std::move(msg));
});
};
}
if (auto conn = ep.get_conn(source); conn)
{
log::critical(logcat, "Dispatched bootstrap fetch request!");
conn->control_stream->command("bfetch_rcs"s, std::move(payload), std::move(f));
log::critical(logcat, "Dispatched bootstrap fetch request!");
return;
}
log::critical(logcat, "Queuing bootstrap fetch request");
auto pending = PendingControlMessage(std::move(payload), "bfetch_rcs"s, f);
log::critical(logcat, "Queuing bootstrap fetch request to {}", source.router_id());
auto pending = PendingControlMessage(std::move(payload), "bfetch_rcs"s, std::move(f));
auto [itr, b] = pending_conn_msg_queue.emplace(source.router_id(), MessageQueue());
itr->second.push_back(std::move(pending));
@ -665,14 +680,19 @@ namespace llarp
return;
}
node_db->put_rc(remote);
auto is_seed = _router.is_bootstrap_seed();
auto& bootstraps = node_db->bootstrap_list();
auto count = bootstraps.size();
auto& src = is_seed ? node_db->bootstrap_seeds() : node_db->get_known_rcs();
auto count = src.size();
if (is_seed)
node_db->bootstrap_seeds().insert(remote);
else
node_db->put_rc(remote);
if (count == 0)
{
log::error(logcat, "No bootstraps locally to send!");
log::error(logcat, "No {} locally to send!", is_seed ? "bootstrap seeds" : "known RCs");
m.respond(messages::ERROR_RESPONSE, true);
return;
}
@ -685,18 +705,17 @@ namespace llarp
{
auto sublist = btdp.append_list("rcs");
while (i < quantity)
for (const auto& rc : src)
{
auto& next_rc = bootstraps.next();
if (not rc.is_expired(now))
sublist.append_encoded(rc.view());
if (next_rc.is_expired(now))
continue;
sublist.append_encoded(next_rc.view());
++i;
if (++i >= quantity)
break;
}
}
m.respond(std::move(btdp).str());
}

View File

@ -181,7 +181,7 @@ namespace llarp
// when establishing a connection, the rid of the remote is placed here to be cross-
// checked by the tls verification callback
std::map<RouterID, RemoteRC> rids_pending_verification;
// in the interim of verifying an inbound connection and the creation of its link::Connection
// in the interim of verifying an outbound connection and the creation of its link::Connection
// object, we store the rid and rc here
std::map<RouterID, RemoteRC> verified_rids;
@ -354,18 +354,9 @@ namespace llarp
{"find_name"sv, &LinkManager::handle_find_name},
{"publish_intro"sv, &LinkManager::handle_publish_intro},
{"find_intro"sv, &LinkManager::handle_find_intro}};
/*
{"path_confirm", &LinkManager::handle_path_confirm},
{"path_latency", &LinkManager::handle_path_latency},
{"update_exit", &LinkManager::handle_update_exit},
{"obtain_exit", &LinkManager::handle_obtain_exit},
{"close_exit", &LinkManager::handle_close_exit},
{"convo_intro", &LinkManager::handle_convo_intro}};
*/
// these requests are direct, i.e. not over a path;
// the rest are relay->relay
// TODO: new RC fetch endpoint (which will be both client->relay and relay->relay)
std::unordered_map<
std::string_view,
void (LinkManager::*)(std::string_view body, std::function<void(std::string)> respond)>
@ -413,6 +404,10 @@ namespace llarp
{
try
{
std::this_thread::sleep_for(5s);
oxen::log::flush();
log::critical(logcat, "Establishing connection to {}", remote);
auto conn_interface =
endpoint->connect(remote, link_manager.tls_creds, std::forward<Opt>(opts)...);
@ -431,6 +426,7 @@ namespace llarp
s.conn.close_connection(error_code);
});
link_manager.register_commands(control_stream);
itr->second = std::make_shared<link::Connection>(conn_interface, control_stream, rc);
return true;

View File

@ -10,6 +10,8 @@
#include <llarp/util/bits.hpp>
#include <llarp/util/mem.hpp>
#include <quic/address.hpp>
#include <cstdlib> // for itoa
#include <functional>
#include <vector>
@ -121,8 +123,10 @@ namespace llarp
return var::visit([](auto&& ip) { return not ip.n; }, ip);
}
virtual std::optional<sockaddr*>
GetBestNetIF(int af = AF_INET) const = 0;
// Attempts to guess a good default public network address from the system's public IP
// addresses; the returned Address (if set) will have its port set to the given value.
virtual std::optional<oxen::quic::Address>
get_best_public_address(bool ipv4, uint16_t port) const = 0;
virtual std::optional<IPRange>
FindFreeRange() const = 0;

View File

@ -10,6 +10,8 @@
#include <ifaddrs.h>
#endif
#include <quic/address.hpp>
#include <list>
namespace llarp::net
@ -50,19 +52,21 @@ namespace llarp::net
return ifname;
}
std::optional<sockaddr*>
GetBestNetIF(int af) const override
std::optional<oxen::quic::Address>
get_best_public_address(bool ipv4, uint16_t port) const override
{
std::optional<sockaddr*> found;
std::optional<oxen::quic::Address> found;
iter_all([this, &found, af](auto i) {
iter_all([&found, ipv4, port](ifaddrs* i) {
if (found)
return;
if (i and i->ifa_addr and i->ifa_addr->sa_family == af)
if (i and i->ifa_addr and i->ifa_addr->sa_family == (ipv4 ? AF_INET : AF_INET6))
{
if (not IsBogon(*i->ifa_addr))
oxen::quic::Address a{i->ifa_addr};
if (a.is_public_ip())
{
found = i->ifa_addr;
a.set_port(port);
found = std::move(a);
}
}
});

View File

@ -129,8 +129,8 @@ namespace llarp::net
return "lokitun0";
}
std::optional<sockaddr*>
GetBestNetIF(int) const override
std::optional<oxen::quic::Address>
get_best_public_address(bool, uint16_t) const override
{
// TODO: implement me ?
return std::nullopt;

View File

@ -192,15 +192,10 @@ namespace llarp
}
void
NodeDB::set_bootstrap_routers(std::unique_ptr<BootstrapList> from_router)
NodeDB::set_bootstrap_routers(BootstrapList& from_router)
{
// TODO: if this needs to be called more than once (ex: drastic failures), then
// change this assert to a bootstraps.clear() call
if (_bootstraps)
assert(_bootstraps->empty());
_bootstraps = std::move(from_router);
_bootstraps->randomize();
_bootstraps.merge(from_router);
_bootstraps.randomize();
}
bool
@ -344,9 +339,9 @@ namespace llarp
void
NodeDB::fetch_initial()
{
if (known_rcs.empty())
if (known_rids.empty())
{
log::critical(logcat, "No RC's held locally... BOOTSTRAP TIME");
log::critical(logcat, "No RouterID's held locally... BOOTSTRAP TIME");
fallback_to_bootstrap();
}
else
@ -610,6 +605,8 @@ namespace llarp
if (_router.is_service_node())
{
_needs_rebootstrap = false;
_needs_initial_fetch = false;
_using_bootstrap_fallback = false;
fail_sources.clear();
fetch_failures = 0;
return;
@ -627,6 +624,7 @@ namespace llarp
_router.last_rid_fetch = llarp::time_point_now();
fetch_counters.clear();
_needs_rebootstrap = false;
_using_bootstrap_fallback = false;
if (initial)
{
@ -638,6 +636,7 @@ namespace llarp
void
NodeDB::fallback_to_bootstrap()
{
log::critical(logcat, "{} called", __PRETTY_FUNCTION__);
auto at_max_failures = bootstrap_attempts >= MAX_BOOTSTRAP_FETCH_ATTEMPTS;
// base case: we have failed to query all bootstraps, or we received a sample of
@ -659,18 +658,21 @@ namespace llarp
bootstrap_cooldown();
return;
}
auto rc = _bootstraps->next();
fetch_source = rc.router_id();
}
auto& rc = (_using_bootstrap_fallback) ? _bootstraps.next() : _bootstraps.current();
fetch_source = rc.router_id();
// By passing the last conditional, we ensure this is set to true
_using_bootstrap_fallback = true;
_needs_rebootstrap = false;
++bootstrap_attempts;
log::critical(
logcat, "Dispatching BootstrapRC fetch request to {}", _bootstraps.current().view());
_router.link_manager().fetch_bootstrap_rcs(
_bootstraps->current(),
rc,
BootstrapFetchMessage::serialize(_router.router_contact, BOOTSTRAP_SOURCE_COUNT),
[this](oxen::quic::message m) mutable {
if (not m)
@ -723,7 +725,7 @@ namespace llarp
if (rids.size() == BOOTSTRAP_SOURCE_COUNT)
{
known_rids.swap(rids);
known_rids.merge(rids);
fetch_initial();
}
else
@ -745,6 +747,7 @@ namespace llarp
NodeDB::bootstrap_cooldown()
{
_needs_rebootstrap = true;
_using_bootstrap_fallback = false;
_router.next_bootstrap_attempt = llarp::time_point_now() + BOOTSTRAP_COOLDOWN;
}
@ -792,7 +795,7 @@ namespace llarp
NodeDB::is_connection_allowed(const RouterID& remote) const
{
if (_pinned_edges.size() && _pinned_edges.count(remote) == 0
&& not _bootstraps->contains(remote))
&& not _bootstraps.contains(remote))
return false;
if (not _router.is_service_node())
@ -810,6 +813,20 @@ namespace llarp
return true;
}
void
NodeDB::store_bootstraps()
{
if (_bootstraps.empty())
return;
for (const auto& rc : _bootstraps)
{
put_rc(rc);
}
log::critical(logcat, "NodeDB stored {} bootstrap routers", _bootstraps.size());
}
void
NodeDB::load_from_disk()
{

View File

@ -121,6 +121,9 @@ namespace llarp
the unknown_rids container
- rc_lookup: holds all the same rc's as known_rcs, but can be used to look them up by
their rid
- bootstrap_seeds: if we are the seed node, we insert the rc's of bootstrap fetch requests
senders into this container to "introduce" them to each other
- _bootstraps: the standard container for bootstrap RemoteRCs
*/
std::set<RouterID> known_rids;
std::set<Unconfirmed<RouterID>> unconfirmed_rids;
@ -130,6 +133,9 @@ namespace llarp
std::map<RouterID, const RemoteRC&> rc_lookup;
std::set<RemoteRC> _bootstrap_seeds;
BootstrapList _bootstraps{};
/** RouterID lists // TODO: get rid of all these, replace with better decom/not staked sets
- white: active routers
- gray: fully funded, but decommissioned routers
@ -178,8 +184,6 @@ namespace llarp
fs::path
get_path_by_pubkey(RouterID pk) const;
std::unique_ptr<BootstrapList> _bootstraps{};
public:
explicit NodeDB(
fs::path rootdir, std::function<void(std::function<void()>)> diskCaller, Router* r);
@ -214,6 +218,9 @@ namespace llarp
return _needs_rebootstrap;
}
void
ingest_bootstrap_seed();
bool
ingest_fetched_rcs(std::set<RemoteRC> rcs, rc_time timestamp);
@ -299,32 +306,47 @@ namespace llarp
return _pinned_edges;
}
void
store_bootstraps();
size_t
num_bootstraps() const
{
return _bootstraps ? _bootstraps->size() : 0;
return _bootstraps.size();
}
bool
has_bootstraps() const
{
return _bootstraps ? _bootstraps->empty() : false;
return _bootstraps.empty();
}
const BootstrapList&
bootstrap_list() const
{
return *_bootstraps;
return _bootstraps;
}
BootstrapList&
bootstrap_list()
{
return *_bootstraps;
return _bootstraps;
}
const std::set<RemoteRC>&
bootstrap_seeds() const
{
return _bootstrap_seeds;
}
std::set<RemoteRC>&
bootstrap_seeds()
{
return _bootstrap_seeds;
}
void
set_bootstrap_routers(std::unique_ptr<BootstrapList> from_router);
set_bootstrap_routers(BootstrapList& from_router);
const std::set<RouterID>&
whitelist() const

View File

@ -582,11 +582,8 @@ namespace llarp
if (paddr or pport)
throw std::runtime_error{"Must specify [bind]:listen in config with public ip/addr!"};
if (auto maybe_addr = net().GetBestNetIF())
{
_listen_address = oxen::quic::Address{static_cast<const sockaddr*>(*maybe_addr)};
_listen_address.set_port(DEFAULT_LISTEN_PORT);
}
if (auto maybe_addr = net().get_best_public_address(true, DEFAULT_LISTEN_PORT))
_listen_address = std::move(*maybe_addr);
else
throw std::runtime_error{"Could not find net interface on current platform!"};
}
@ -631,17 +628,19 @@ namespace llarp
configRouters.push_back(defaultBootstrapFile);
}
auto _bootstrap_rc_list = std::make_unique<BootstrapList>();
// BootstrapList _bootstrap_rc_list;
auto& node_bstrap = _node_db->bootstrap_list();
auto clear_bad_rcs = [&]() mutable {
log::critical(logcat, "Clearing bad RCs...");
// in case someone has an old bootstrap file and is trying to use a bootstrap
// that no longer exists
for (auto it = _bootstrap_rc_list->begin(); it != _bootstrap_rc_list->end();)
for (auto it = node_bstrap.begin(); it != node_bstrap.end();)
{
if (it->is_obsolete_bootstrap())
log::warning(logcat, "ignoring obsolete bootstrap RC: {}", it->router_id());
log::critical(logcat, "ignoring obsolete bootstrap RC: {}", it->router_id());
else if (not it->verify())
log::warning(logcat, "ignoring invalid bootstrap RC: {}", it->router_id());
log::critical(logcat, "ignoring invalid bootstrap RC: {}", it->router_id());
else
{
++it;
@ -649,29 +648,30 @@ namespace llarp
}
// we are in one of the above error cases that we warned about:
it = _bootstrap_rc_list->erase(it);
it = node_bstrap.erase(it);
}
};
for (const auto& router : configRouters)
{
log::debug(logcat, "Loading bootstrap router list from {}", defaultBootstrapFile);
_bootstrap_rc_list->read_from_file(router);
node_bstrap.read_from_file(router);
// _bootstrap_rc_list.read_from_file(router);
}
for (const auto& rc : conf.bootstrap.routers)
{
_bootstrap_rc_list->emplace(rc);
// _bootstrap_rc_list.emplace(rc);
node_bstrap.emplace(rc);
}
clear_bad_rcs();
_bootstrap_seed = conf.bootstrap.seednode;
if (_bootstrap_seed)
log::critical(logcat, "We are a bootstrap seed node!");
if (_bootstrap_rc_list->empty() and not _bootstrap_seed)
if (node_bstrap.empty() and not _bootstrap_seed)
{
log::warning(logcat, "Warning: bootstrap list is empty and we are not a seed node");
@ -679,10 +679,11 @@ namespace llarp
if (auto itr = fallbacks.find(RouterContact::ACTIVE_NETID); itr != fallbacks.end())
{
_bootstrap_rc_list->merge(itr->second);
// _bootstrap_rc_list.merge(itr->second);
node_bstrap.merge(itr->second);
}
if (_bootstrap_rc_list->empty())
if (node_bstrap.empty())
{
// empty after trying fallback, if set
log::error(
@ -694,20 +695,20 @@ namespace llarp
throw std::runtime_error("No bootstrap nodes available.");
}
log::info(
logcat, "Loaded {} default fallback bootstrap routers!", _bootstrap_rc_list->size());
clear_bad_rcs();
log::critical(
logcat, "Loaded {} default fallback bootstrap routers!", node_bstrap.size());
}
log::critical(logcat, "We have {} bootstrap routers!", _bootstrap_rc_list->size());
clear_bad_rcs();
log::critical(logcat, "We have {} bootstrap routers!", node_bstrap.size());
node_db()->set_bootstrap_routers(std::move(_bootstrap_rc_list));
// node_db()->set_bootstrap_routers(_bootstrap_rc_list);
// TODO: RC refactor here
if (_is_service_node)
init_inbounds();
else
init_outbounds();
// if (_is_service_node)
// init_inbounds();
// else
// init_outbounds();
// profiling
_profile_file = conf.router.data_dir / "profiles.dat";
@ -1118,7 +1119,7 @@ namespace llarp
}
log::info(logcat, "Router initialized as service node!");
const RouterID us = pubkey();
// relays do not use profiling
router_profiling().Disable();
}
@ -1140,21 +1141,13 @@ namespace llarp
log::info(logcat, "Loading NodeDB from disk...");
_node_db->load_from_disk();
_node_db->store_bootstraps();
oxen::log::flush();
log::info(logcat, "Creating Introset Contacts...");
_contacts = std::make_unique<Contacts>(*this);
if (_node_db->has_bootstraps())
{
for (const auto& rc : _node_db->bootstrap_list())
{
node_db()->put_rc(rc);
log::info(logcat, "Added bootstrap node (rid: {})", rc.router_id());
}
log::info(logcat, "Router populated NodeDB with {} routers", _node_db->num_rcs());
}
_loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); });
_route_poker->start();
@ -1163,7 +1156,7 @@ namespace llarp
_started_at = now();
if (is_service_node())
if (is_service_node() and not _testing_disabled)
{
// do service node testing if we are in service node whitelist mode
_loop->call_every(consensus::REACHABILITY_TESTING_TIMER_INTERVAL, weak_from_this(), [this] {
@ -1225,6 +1218,7 @@ namespace llarp
}
});
}
llarp::sys::service_manager->ready();
return is_running;
}

View File

@ -105,7 +105,7 @@ namespace llarp
std::shared_ptr<NodeDB> _node_db;
llarp_time_t _started_at;
const oxenmq::TaggedThreadID _disk_thread;
oxen::quic::Network _net;
// oxen::quic::Network _net; // DISCUSS: we don't use this anywhere..?
llarp_time_t _last_stats_report = 0s;
llarp_time_t _next_decomm_warning = time_now_ms() + 15s;

View File

@ -56,6 +56,7 @@ namespace llarp
}
auto netid = data.maybe<std::string_view>("i").value_or(llarp::LOKINET_DEFAULT_NETID);
if (netid != ACTIVE_NETID)
throw std::runtime_error{
"Invalid RC netid: expected {}, got {}; this is an RC for a different network!"_format(
@ -67,14 +68,7 @@ namespace llarp
"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())};
std::memcpy(_router_id.data(), pubkey.data(), 32);
// auto pk = data.require<std::string_view>("p");
// if (pk.size() != RouterID::SIZE)
// throw std::runtime_error{"Invalid RC: router id has invalid size {}"_format(pk.size())};
// std::memcpy(_router_id.data(), pk.data(), RouterID::SIZE);
_timestamp = rc_time{std::chrono::seconds{data.require<int64_t>("t")}};
_timestamp = rc_time{std::chrono::seconds{data.require<uint64_t>("t")}};
auto ver = data.require<ustring_view>("v");

View File

@ -16,7 +16,6 @@ namespace llarp
try
{
bt_load(btdc);
bt_verify(btdc, /*reject_expired=*/true);
}
catch (const std::exception& e)