Storage server RPC improvements

Improves the oxend<->storage server communications protocol:

- pass storage server HTTPS port as part of the storage server ping
(which already carries the also-required OMQ port) rather than needing
to provide it when starting up oxend.  --storage-server-port is now
obsolete (and ignored, if specified).
- Fix up the internal API to use `storage_https_port` and
`storage_omq_port` rather than `storage_port` and `storage_lmq_port`.
- Redo and the SS ping RPC endpoint so that it is less verbose and more
closely matches the lokinet endpoint; instead of:

    { "version_major": 2, "version_minor": 0, "version_patch": 9, "storage_lmq_port": 22222 }

we now expect:

    { "version": [2,0,9], "https_port": 11111, "omq_port": 22222 }

- Tweaks the (not-yet-released) SS proof key names: "s"->"shp" and "slp"->"sop"
This commit is contained in:
Jason Rhinelander 2021-04-08 13:42:33 -03:00
parent 2f5ec0e1e6
commit ce9d0a9c1e
13 changed files with 79 additions and 85 deletions

View File

@ -180,7 +180,7 @@ namespace cryptonote
};
static const command_line::arg_descriptor<bool> arg_service_node = {
"service-node"
, "Run as a service node, options 'service-node-public-ip' and 'storage-server-port' must be set"
, "Run as a service node, option 'service-node-public-ip' must be set"
};
static const command_line::arg_descriptor<std::string> arg_public_ip = {
"service-node-public-ip"
@ -190,11 +190,7 @@ namespace cryptonote
"service node."
};
static const command_line::arg_descriptor<uint16_t> arg_storage_server_port = {
"storage-server-port"
, "The port on which this service node's storage server is accessible. A listening "
"storage server is required for service nodes. (This option is specified "
"automatically when using Loki Launcher.)"
, 0};
"storage-server-port", "Deprecated option, ignored.", 0};
static const command_line::arg_descriptor<uint16_t, false, true, 2> arg_quorumnet_port = {
"quorumnet-port"
, "The port on which this service node listen for direct connections from other "
@ -394,16 +390,9 @@ namespace cryptonote
if (m_service_node) {
/// TODO: parse these options early, before we start p2p server etc?
m_storage_port = command_line::get_arg(vm, arg_storage_server_port);
m_quorumnet_port = command_line::get_arg(vm, arg_quorumnet_port);
bool args_okay = true;
if (m_storage_port == 0 && m_nettype != DEVNET) {
MERROR("Please specify the port on which the storage server is listening with: '--" << arg_storage_server_port.name << " <port>'");
storage_ok = false;
}
if (m_quorumnet_port == 0) {
MERROR("Quorumnet port cannot be 0; please specify a valid port to listen on with: '--" << arg_quorumnet_port.name << " <port>'");
args_okay = false;
@ -433,14 +422,10 @@ namespace cryptonote
}
if (!args_okay) {
MERROR("IMPORTANT: All service node operators are now required to run the oxen storage "
<< "server and provide the public ip and ports on which it can be accessed on the internet.");
MERROR("IMPORTANT: One or more required service node-related configuration settings/options were omitted or invalid; "
<< "please fix them and restart oxend.");
return false;
}
MGINFO("Storage server endpoint is set to: "
<< (epee::net_utils::ipv4_network_address{ m_sn_public_ip, m_storage_port }).str());
}
return true;
@ -1938,10 +1923,10 @@ namespace cryptonote
auto hf_version = get_hard_fork_version(height);
//TODO: remove after HF18
if (hf_version < HF_VERSION_PROOF_BTENC) {
NOTIFY_UPTIME_PROOF::request req = m_service_node_list.generate_uptime_proof(m_sn_public_ip, m_storage_port, m_storage_lmq_port, m_quorumnet_port);
NOTIFY_UPTIME_PROOF::request req = m_service_node_list.generate_uptime_proof(m_sn_public_ip, storage_https_port(), storage_omq_port(), m_quorumnet_port);
relayed = get_protocol()->relay_uptime_proof(req, fake_context);
} else {
auto proof = m_service_node_list.generate_uptime_proof(m_sn_public_ip, m_storage_port, m_storage_lmq_port, ss_version, m_quorumnet_port, lokinet_version);
auto proof = m_service_node_list.generate_uptime_proof(m_sn_public_ip, storage_https_port(), storage_omq_port(), ss_version, m_quorumnet_port, lokinet_version);
NOTIFY_BTENCODED_UPTIME_PROOF::request req = proof.generate_request();
relayed = get_protocol()->relay_btencoded_uptime_proof(req, fake_context);
}
@ -2332,11 +2317,11 @@ namespace cryptonote
m_service_node_list.for_each_service_node_info_and_proof(sn_pks.begin(), sn_pks.end(), [&](auto& pk, auto& sni, auto& proof) {
if (pk != m_service_keys.pub && proof.proof->public_ip == m_sn_public_ip &&
(proof.proof->qnet_port == m_quorumnet_port || proof.proof->storage_port == m_storage_port || proof.proof->storage_port == m_storage_lmq_port))
(proof.proof->qnet_port == m_quorumnet_port || proof.proof->storage_https_port == storage_https_port() || proof.proof->storage_omq_port == storage_omq_port()))
MGINFO_RED(
"Another service node (" << pk << ") is broadcasting the same public IP and ports as this service node (" <<
epee::string_tools::get_ip_string_from_int32(m_sn_public_ip) << ":" << proof.proof->qnet_port << "[qnet], :" <<
proof.proof->storage_port << "[SS-HTTP], :" << proof.proof->storage_lmq_port << "[SS-LMQ]). "
proof.proof->storage_https_port << "[SS-HTTP], :" << proof.proof->storage_omq_port << "[SS-LMQ]). "
"This will lead to deregistration of one or both service nodes if not corrected. "
"(Do both service nodes have the correct IP for the service-node-public-ip setting?)");
});

View File

@ -1024,10 +1024,11 @@ namespace cryptonote
/// Time point at which the storage server and lokinet last pinged us
std::atomic<time_t> m_last_storage_server_ping, m_last_lokinet_ping;
std::atomic<uint16_t> m_storage_lmq_port;
std::atomic<uint16_t> m_storage_https_port, m_storage_omq_port;
uint32_t sn_public_ip() const { return m_sn_public_ip; }
uint16_t storage_port() const { return m_storage_port; }
uint16_t storage_https_port() const { return m_storage_https_port; }
uint16_t storage_omq_port() const { return m_storage_omq_port; }
uint16_t quorumnet_port() const { return m_quorumnet_port; }
/**
@ -1244,9 +1245,8 @@ namespace cryptonote
bool m_service_node; // True if running in service node mode
service_keys m_service_keys; // Always set, even for non-SN mode -- these can be used for public oxenmq rpc
/// Service Node's public IP and storage server port (http and oxenmq)
/// Service Node's public IP and qnet ports
uint32_t m_sn_public_ip;
uint16_t m_storage_port;
uint16_t m_quorumnet_port;
/// OxenMQ main object. Gets created during init().

View File

@ -2753,14 +2753,14 @@ namespace service_nodes
size_t buf_size;
crypto::hash result;
auto buf = tools::memcpy_le(proof.pubkey.data, proof.timestamp, proof.public_ip, proof.storage_port, proof.pubkey_ed25519.data, proof.qnet_port, proof.storage_lmq_port);
auto buf = tools::memcpy_le(proof.pubkey.data, proof.timestamp, proof.public_ip, proof.storage_https_port, proof.pubkey_ed25519.data, proof.qnet_port, proof.storage_omq_port);
buf_size = buf.size();
crypto::cn_fast_hash(buf.data(), buf_size, result);
return result;
}
cryptonote::NOTIFY_UPTIME_PROOF::request service_node_list::generate_uptime_proof(
uint32_t public_ip, uint16_t storage_port, uint16_t storage_lmq_port, uint16_t quorumnet_port) const
uint32_t public_ip, uint16_t storage_https_port, uint16_t storage_omq_port, uint16_t quorumnet_port) const
{
assert(m_service_node_keys);
const auto& keys = *m_service_node_keys;
@ -2769,8 +2769,8 @@ namespace service_nodes
result.timestamp = time(nullptr);
result.pubkey = keys.pub;
result.public_ip = public_ip;
result.storage_port = storage_port;
result.storage_lmq_port = storage_lmq_port;
result.storage_https_port = storage_https_port;
result.storage_omq_port = storage_omq_port;
result.qnet_port = quorumnet_port;
result.pubkey_ed25519 = keys.pub_ed25519;
@ -2780,10 +2780,10 @@ namespace service_nodes
return result;
}
uptime_proof::Proof service_node_list::generate_uptime_proof(uint32_t public_ip, uint16_t storage_port, uint16_t storage_lmq_port, std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, std::array<uint16_t, 3> lokinet_version) const
uptime_proof::Proof service_node_list::generate_uptime_proof(uint32_t public_ip, uint16_t storage_https_port, uint16_t storage_omq_port, std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, std::array<uint16_t, 3> lokinet_version) const
{
const auto& keys = *m_service_node_keys;
return uptime_proof::Proof(public_ip, storage_port, storage_lmq_port, ss_version, quorumnet_port, lokinet_version, keys);
return uptime_proof::Proof(public_ip, storage_https_port, storage_omq_port, ss_version, quorumnet_port, lokinet_version, keys);
}
#ifdef __cpp_lib_erase_if // # (C++20)
@ -2853,8 +2853,8 @@ namespace service_nodes
//TODO remove after HF18
bool proof_info::update(uint64_t ts,
uint32_t ip,
uint16_t s_port,
uint16_t s_lmq_port,
uint16_t s_https_port,
uint16_t s_omq_port,
uint16_t q_port,
std::array<uint16_t, 3> ver,
const crypto::ed25519_public_key& pk_ed,
@ -2864,8 +2864,8 @@ namespace service_nodes
if (!proof) proof = std::unique_ptr<uptime_proof::Proof>(new uptime_proof::Proof());
update_db |= update_val(timestamp, ts);
update_db |= update_val(proof->public_ip, ip);
update_db |= update_val(proof->storage_port, s_port);
update_db |= update_val(proof->storage_lmq_port, s_lmq_port);
update_db |= update_val(proof->storage_https_port, s_https_port);
update_db |= update_val(proof->storage_omq_port, s_omq_port);
update_db |= update_val(proof->qnet_port, q_port);
update_db |= update_val(proof->version, ver);
update_db |= update_val(proof->pubkey_ed25519, pk_ed);
@ -2973,7 +2973,7 @@ namespace service_nodes
}
auto old_x25519 = iproof.pubkey_x25519;
if (iproof.update(std::chrono::system_clock::to_time_t(now), proof.public_ip, proof.storage_port, proof.storage_lmq_port, proof.qnet_port, proof.snode_version, proof.pubkey_ed25519, derived_x25519_pubkey))
if (iproof.update(std::chrono::system_clock::to_time_t(now), proof.public_ip, proof.storage_https_port, proof.storage_omq_port, proof.qnet_port, proof.snode_version, proof.pubkey_ed25519, derived_x25519_pubkey))
iproof.store(proof.pubkey, m_blockchain);
if (now - x25519_map_last_pruned >= X25519_MAP_PRUNING_INTERVAL)

View File

@ -172,7 +172,7 @@ namespace service_nodes
// caller's responsibility).
bool update(uint64_t ts, std::unique_ptr<uptime_proof::Proof> new_proof, const crypto::x25519_public_key &pk_x2);
// TODO: remove after HF18
bool update(uint64_t ts, uint32_t ip, uint16_t s_port, uint16_t s_lmq_port, uint16_t q_port, std::array<uint16_t, 3> ver, const crypto::ed25519_public_key &pk_ed, const crypto::x25519_public_key &pk_x2);
bool update(uint64_t ts, uint32_t ip, uint16_t s_https_port, uint16_t s_omq_port, uint16_t q_port, std::array<uint16_t, 3> ver, const crypto::ed25519_public_key &pk_ed, const crypto::x25519_public_key &pk_x2);
// Stores this record in the database.
void store(const crypto::public_key &pubkey, cryptonote::Blockchain &blockchain);
@ -529,11 +529,11 @@ namespace service_nodes
/// Record public ip and storage port and add them to the service node list
//TODO: remove after HF18
cryptonote::NOTIFY_UPTIME_PROOF::request generate_uptime_proof(uint32_t public_ip,
uint16_t storage_port,
uint16_t storage_lmq_port,
uint16_t storage_https_port,
uint16_t storage_omq_port,
uint16_t quorumnet_port) const;
uptime_proof::Proof generate_uptime_proof(uint32_t public_ip, uint16_t storage_port, uint16_t storage_lmq_port, std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, std::array<uint16_t, 3> lokinet_version) const;
uptime_proof::Proof generate_uptime_proof(uint32_t public_ip, uint16_t storage_port, uint16_t storage_omq_port, std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, std::array<uint16_t, 3> lokinet_version) const;
//TODO: remove after HF18
bool handle_uptime_proof(cryptonote::NOTIFY_UPTIME_PROOF::request const &proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey);

View File

@ -211,7 +211,7 @@ namespace service_nodes {
// blocks out of sync and sending something that it thinks is legit.
constexpr uint64_t VOTE_OR_TX_VERIFY_HEIGHT_BUFFER = 5;
constexpr std::array<uint16_t, 3> MIN_STORAGE_SERVER_VERSION{{2, 0, 7}};
constexpr std::array<uint16_t, 3> MIN_STORAGE_SERVER_VERSION{{2, 0, 9}};
constexpr std::array<uint16_t, 3> MIN_LOKINET_VERSION{{0, 8, 0}};
// The minimum accepted version number, broadcasted by Service Nodes via uptime proofs for each hardfork

View File

@ -14,7 +14,23 @@ namespace uptime_proof
{
//Constructor for the uptime proof, will take the service node keys as a param and sign
Proof::Proof(uint32_t sn_public_ip, uint16_t sn_storage_port, uint16_t sn_storage_lmq_port, const std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, const std::array<uint16_t, 3> lokinet_version, const service_nodes::service_node_keys& keys) : version{OXEN_VERSION}, pubkey{keys.pub}, timestamp{static_cast<uint64_t>(time(nullptr))}, public_ip{sn_public_ip}, storage_port{sn_storage_port}, pubkey_ed25519{keys.pub_ed25519},qnet_port{quorumnet_port}, storage_lmq_port{sn_storage_lmq_port}, storage_server_version{ss_version}
Proof::Proof(
uint32_t sn_public_ip,
uint16_t sn_storage_https_port,
uint16_t sn_storage_omq_port,
const std::array<uint16_t, 3> ss_version,
uint16_t quorumnet_port,
const std::array<uint16_t, 3> lokinet_version,
const service_nodes::service_node_keys& keys) :
version{OXEN_VERSION},
pubkey{keys.pub},
timestamp{static_cast<uint64_t>(time(nullptr))},
public_ip{sn_public_ip},
pubkey_ed25519{keys.pub_ed25519},
qnet_port{quorumnet_port},
storage_https_port{sn_storage_https_port},
storage_omq_port{sn_storage_omq_port},
storage_server_version{ss_version}
{
this->lokinet_version = lokinet_version;
crypto::hash hash = this->hash_uptime_proof();
@ -41,7 +57,7 @@ Proof::Proof(const std::string& serialized_proof)
//public_ip
bool succeeded = epee::string_tools::get_ip_int32_from_string(public_ip, var::get<std::string>(bt_proof.at("ip")));
//storage_port
storage_port = static_cast<uint16_t>(get_int<unsigned>(bt_proof.at("s")));
storage_https_port = static_cast<uint16_t>(get_int<unsigned>(bt_proof.at("shp")));
//pubkey_ed25519
pubkey_ed25519 = tools::make_from_guts<crypto::ed25519_public_key>(var::get<std::string>(bt_proof.at("pke")));
//pubkey
@ -51,8 +67,8 @@ Proof::Proof(const std::string& serialized_proof)
std::memcpy(pubkey.data, pubkey_ed25519.data, 32);
//qnet_port
qnet_port = get_int<unsigned>(bt_proof.at("q"));
//storage_lmq_port
storage_lmq_port = get_int<unsigned>(bt_proof.at("slp"));
//storage_omq_port
storage_omq_port = get_int<unsigned>(bt_proof.at("sop"));
//storage_version
const bt_list& bt_storage_version = var::get<bt_list>(bt_proof.at("sv"));
k = 0;
@ -92,13 +108,13 @@ oxenmq::bt_dict Proof::bt_encode_uptime_proof() const
//public_ip
{"ip", epee::string_tools::get_ip_string_from_int32(public_ip)},
//storage_port
{"s", storage_port},
{"shp", storage_https_port},
//pubkey_ed25519
{"pke", tools::view_guts(pubkey_ed25519)},
//qnet_port
{"q", qnet_port},
//storage_lmq_port
{"slp", storage_lmq_port},
//storage_omq_port
{"sop", storage_omq_port},
//storage_version
{"sv", oxenmq::bt_list{{storage_server_version[0], storage_server_version[1], storage_server_version[2]}}},
//lokinet_version
@ -132,18 +148,12 @@ bool operator==(const uptime_proof::Proof& lhs, const uptime_proof::Proof& rhs)
(lhs.pubkey_ed25519 != rhs.pubkey_ed25519) ||
(lhs.sig_ed25519 != rhs.sig_ed25519) ||
(lhs.public_ip != rhs.public_ip) ||
(lhs.storage_port != rhs.storage_port) ||
(lhs.storage_lmq_port != rhs.storage_lmq_port) ||
(lhs.storage_https_port != rhs.storage_https_port) ||
(lhs.storage_omq_port != rhs.storage_omq_port) ||
(lhs.qnet_port != rhs.qnet_port) ||
(lhs.version[0] != rhs.version[0]) ||
(lhs.version[1] != rhs.version[1]) ||
(lhs.version[2] != rhs.version[2]) ||
(lhs.storage_server_version[0] != rhs.storage_server_version[0]) ||
(lhs.storage_server_version[1] != rhs.storage_server_version[1]) ||
(lhs.storage_server_version[2] != rhs.storage_server_version[2]) ||
(lhs.lokinet_version[0] != rhs.lokinet_version[0]) ||
(lhs.lokinet_version[1] != rhs.lokinet_version[1]) ||
(lhs.lokinet_version[2] != rhs.lokinet_version[2]))
(lhs.version != rhs.version) ||
(lhs.storage_server_version != rhs.storage_server_version) ||
(lhs.lokinet_version != rhs.lokinet_version))
result = false;
return result;

View File

@ -21,12 +21,12 @@ public:
crypto::ed25519_public_key pubkey_ed25519;
crypto::ed25519_signature sig_ed25519;
uint32_t public_ip;
uint16_t storage_port;
uint16_t storage_lmq_port;
uint16_t storage_https_port;
uint16_t storage_omq_port;
uint16_t qnet_port;
Proof() = default;
Proof(uint32_t sn_public_ip, uint16_t sn_storage_port, uint16_t sn_storage_lmq_port, std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, std::array<uint16_t, 3> lokinet_version, const service_nodes::service_node_keys& keys);
Proof(uint32_t sn_public_ip, uint16_t sn_storage_https_port, uint16_t sn_storage_omq_port, std::array<uint16_t, 3> ss_version, uint16_t quorumnet_port, std::array<uint16_t, 3> lokinet_version, const service_nodes::service_node_keys& keys);
Proof(const std::string& serialized_proof);
oxenmq::bt_dict bt_encode_uptime_proof() const;

View File

@ -110,8 +110,8 @@ KV_SERIALIZE_MAP_CODE_BEGIN(NOTIFY_UPTIME_PROOF::request)
KV_SERIALIZE_N(snode_version[2], "snode_version_patch")
KV_SERIALIZE(timestamp)
KV_SERIALIZE(public_ip)
KV_SERIALIZE(storage_port)
KV_SERIALIZE(storage_lmq_port)
KV_SERIALIZE_N(storage_https_port, "storage_port")
KV_SERIALIZE_N(storage_omq_port, "storage_lmq_port")
KV_SERIALIZE(qnet_port)
KV_SERIALIZE_VAL_POD_AS_BLOB(pubkey)
KV_SERIALIZE_VAL_POD_AS_BLOB(sig)

View File

@ -259,8 +259,8 @@ namespace cryptonote
crypto::ed25519_public_key pubkey_ed25519;
crypto::ed25519_signature sig_ed25519;
uint32_t public_ip;
uint16_t storage_port;
uint16_t storage_lmq_port;
uint16_t storage_https_port;
uint16_t storage_omq_port;
uint16_t qnet_port;
KV_MAP_SERIALIZABLE

View File

@ -1667,8 +1667,8 @@ static void append_printable_service_node_list_entry(cryptonote::network_type ne
if (entry.public_ip == "0.0.0.0")
stream << "(Awaiting confirmation from network)";
else
stream << entry.public_ip << " :" << entry.storage_port << " (storage), :" << entry.storage_lmq_port
<< " (storage lmq), :" << entry.quorumnet_port << " (quorumnet)";
stream << entry.public_ip << " :" << entry.storage_port << " (storage https), :" << entry.storage_lmq_port
<< " (storage omq), :" << entry.quorumnet_port << " (quorumnet)";
stream << "\n";
if (detailed_view)

View File

@ -2329,8 +2329,8 @@ namespace cryptonote { namespace rpc {
{
res.service_node_state.service_node_pubkey = std::move(get_service_node_key_res.service_node_pubkey);
res.service_node_state.public_ip = epee::string_tools::get_ip_string_from_int32(m_core.sn_public_ip());
res.service_node_state.storage_port = m_core.storage_port();
res.service_node_state.storage_lmq_port = m_core.m_storage_lmq_port;
res.service_node_state.storage_port = m_core.storage_https_port();
res.service_node_state.storage_lmq_port = m_core.storage_omq_port();
res.service_node_state.quorumnet_port = m_core.quorumnet_port();
res.service_node_state.pubkey_ed25519 = std::move(get_service_node_key_res.service_node_ed25519_pubkey);
res.service_node_state.pubkey_x25519 = std::move(get_service_node_key_res.service_node_x25519_pubkey);
@ -3050,8 +3050,8 @@ namespace cryptonote { namespace rpc {
entry.lokinet_version = proof.proof->lokinet_version;
entry.storage_server_version = proof.proof->storage_server_version;
entry.public_ip = epee::string_tools::get_ip_string_from_int32(proof.proof->public_ip);
entry.storage_port = proof.proof->storage_port;
entry.storage_lmq_port = proof.proof->storage_lmq_port;
entry.storage_port = proof.proof->storage_https_port;
entry.storage_lmq_port = proof.proof->storage_omq_port;
entry.storage_server_reachable = proof.storage_server_reachable;
entry.pubkey_ed25519 = proof.proof->pubkey_ed25519 ? tools::type_to_hex(proof.proof->pubkey_ed25519) : "";
entry.pubkey_x25519 = proof.pubkey_x25519 ? tools::type_to_hex(proof.pubkey_x25519) : "";
@ -3317,12 +3317,13 @@ namespace cryptonote { namespace rpc {
//------------------------------------------------------------------------------------------------------------------------------
STORAGE_SERVER_PING::response core_rpc_server::invoke(STORAGE_SERVER_PING::request&& req, rpc_context context)
{
m_core.ss_version = {req.version_major, req.version_minor, req.version_patch};
m_core.ss_version = req.version;
return handle_ping<STORAGE_SERVER_PING>(
{req.version_major, req.version_minor, req.version_patch}, service_nodes::MIN_STORAGE_SERVER_VERSION,
req.version, service_nodes::MIN_STORAGE_SERVER_VERSION,
"Storage Server", m_core.m_last_storage_server_ping, m_core.get_net_config().UPTIME_PROOF_FREQUENCY,
[this, &req](bool significant) {
m_core.m_storage_lmq_port = req.storage_lmq_port;
m_core.m_storage_https_port = req.https_port;
m_core.m_storage_omq_port = req.omq_port;
if (significant)
m_core.reset_proof_interval();
});

View File

@ -1211,10 +1211,9 @@ KV_SERIALIZE_MAP_CODE_END()
KV_SERIALIZE_MAP_CODE_BEGIN(STORAGE_SERVER_PING::request)
KV_SERIALIZE(version_major);
KV_SERIALIZE(version_minor);
KV_SERIALIZE(version_patch);
KV_SERIALIZE(storage_lmq_port);
KV_SERIALIZE(version);
KV_SERIALIZE(https_port);
KV_SERIALIZE(omq_port);
KV_SERIALIZE_MAP_CODE_END()

View File

@ -2193,10 +2193,9 @@ namespace rpc {
struct request
{
uint16_t version_major; // Storage Server Major version
uint16_t version_minor; // Storage Server Minor version
uint16_t version_patch; // Storage Server Patch version
uint16_t storage_lmq_port; // Storage Server lmq port to include in uptime proofs
std::array<uint16_t, 3> version; // Storage server version
uint16_t https_port; // Storage server https port to include in uptime proofs
uint16_t omq_port; // Storage Server oxenmq port to include in uptime proofs
KV_MAP_SERIALIZABLE
};