mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
Merge pull request #1370 from darcys22/1366-uptime-proof-version-details
Uptime proof version details + bt-encoded proofs
This commit is contained in:
commit
4c1d03576e
53 changed files with 708 additions and 96 deletions
|
@ -33,6 +33,8 @@
|
||||||
#include <boost/endian/conversion.hpp>
|
#include <boost/endian/conversion.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
#include "epee/string_tools.h"
|
#include "epee/string_tools.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
|
@ -46,6 +48,7 @@
|
||||||
#include "checkpoints/checkpoints.h"
|
#include "checkpoints/checkpoints.h"
|
||||||
#include "cryptonote_core/service_node_rules.h"
|
#include "cryptonote_core/service_node_rules.h"
|
||||||
#include "cryptonote_core/service_node_list.h"
|
#include "cryptonote_core/service_node_list.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "cryptonote_basic/hardfork.h"
|
#include "cryptonote_basic/hardfork.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
|
@ -269,8 +272,15 @@ void lmdb_db_open(MDB_txn* txn, const char* name, int flags, MDB_dbi& dbi, const
|
||||||
throw0(cryptonote::DB_OPEN_FAILURE((lmdb_error(error_string + " : ", res) + std::string(" - you may want to start with --db-salvage")).c_str()));
|
throw0(cryptonote::DB_OPEN_FAILURE((lmdb_error(error_string + " : ", res) + std::string(" - you may want to start with --db-salvage")).c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename...>
|
||||||
|
struct first_type { using type = T; };
|
||||||
|
template <typename... T>
|
||||||
|
using first_type_t = typename first_type<T...>::type;
|
||||||
|
|
||||||
// Lets you iterator over all the pairs of K/V pairs in a database
|
// Lets you iterator over all the pairs of K/V pairs in a database
|
||||||
template <typename K, typename V>
|
// If multiple V are provided then value will be a variant<V1*, V2*, ...> with the populated pointer
|
||||||
|
// matched by size of the record.
|
||||||
|
template <typename K, typename... V>
|
||||||
class iterable_db {
|
class iterable_db {
|
||||||
private:
|
private:
|
||||||
MDB_cursor* cursor;
|
MDB_cursor* cursor;
|
||||||
|
@ -281,13 +291,13 @@ public:
|
||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
public:
|
public:
|
||||||
using value_type = std::pair<K*, V*>;
|
using value_type = std::pair<K*, std::conditional_t<sizeof...(V) == 1, first_type_t<V...>*, std::variant<V*...>>>;
|
||||||
using reference = value_type&;
|
using reference = value_type&;
|
||||||
using pointer = value_type*;
|
using pointer = value_type*;
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
using iterator_category = std::input_iterator_tag;
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
|
||||||
constexpr iterator() : element{nullptr, nullptr} {}
|
constexpr iterator() : element{} {}
|
||||||
iterator(MDB_cursor* c, MDB_cursor_op op_start, MDB_cursor_op op_incr) : cursor{c}, op_incr{op_incr} {
|
iterator(MDB_cursor* c, MDB_cursor_op op_start, MDB_cursor_op op_incr) : cursor{c}, op_incr{op_incr} {
|
||||||
next(op_start);
|
next(op_start);
|
||||||
}
|
}
|
||||||
|
@ -302,14 +312,29 @@ public:
|
||||||
bool operator!=(const iterator& i) const { return !(*this == i); }
|
bool operator!=(const iterator& i) const { return !(*this == i); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename T, typename... More>
|
||||||
|
void load_variant() {
|
||||||
|
if (v.mv_size == sizeof(T))
|
||||||
|
element.second = static_cast<T*>(v.mv_data);
|
||||||
|
else if constexpr (sizeof...(More))
|
||||||
|
load_variant<More...>();
|
||||||
|
else {
|
||||||
|
MWARNING("Invalid stored type size in iterable_db: stored size (" << v.mv_size <<
|
||||||
|
") matched none of " << tools::type_name<value_type>());
|
||||||
|
var::get<0>(element.second) = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void next(MDB_cursor_op op) {
|
void next(MDB_cursor_op op) {
|
||||||
int result = mdb_cursor_get(cursor, &k, &v, op);
|
int result = mdb_cursor_get(cursor, &k, &v, op);
|
||||||
if (result == MDB_NOTFOUND) {
|
if (result == MDB_NOTFOUND) {
|
||||||
element.first = nullptr;
|
element = {};
|
||||||
element.second = nullptr;
|
|
||||||
} else if (result == MDB_SUCCESS) {
|
} else if (result == MDB_SUCCESS) {
|
||||||
element.first = static_cast<K*>(k.mv_data);
|
element.first = static_cast<K*>(k.mv_data);
|
||||||
element.second = static_cast<V*>(v.mv_data);
|
if constexpr (sizeof...(V) == 1)
|
||||||
|
element.second = static_cast<typename value_type::second_type*>(v.mv_data);
|
||||||
|
else
|
||||||
|
load_variant<V...>();
|
||||||
} else {
|
} else {
|
||||||
throw0(cryptonote::DB_ERROR(lmdb_error("enumeration failed: ", result)));
|
throw0(cryptonote::DB_ERROR(lmdb_error("enumeration failed: ", result)));
|
||||||
}
|
}
|
||||||
|
@ -318,7 +343,7 @@ public:
|
||||||
MDB_cursor* cursor = nullptr;
|
MDB_cursor* cursor = nullptr;
|
||||||
const MDB_cursor_op op_incr = MDB_NEXT;
|
const MDB_cursor_op op_incr = MDB_NEXT;
|
||||||
MDB_val k, v;
|
MDB_val k, v;
|
||||||
std::pair<K*, V*> element;
|
value_type element;
|
||||||
};
|
};
|
||||||
|
|
||||||
iterator begin() { return {cursor, op_start, op_incr}; }
|
iterator begin() { return {cursor, op_start, op_incr}; }
|
||||||
|
@ -6240,31 +6265,47 @@ void BlockchainLMDB::clear_service_node_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct service_node_proof_serialized
|
template <typename C>
|
||||||
|
C native_to_little_container(const C& c) {
|
||||||
|
C result{c};
|
||||||
|
for (auto& x : result) native_to_little_inplace(x);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
template <typename C>
|
||||||
|
C little_to_native_container(const C& c) {
|
||||||
|
C result{c};
|
||||||
|
for (auto& x : result) little_to_native_inplace(x);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct service_node_proof_serialized_old
|
||||||
{
|
{
|
||||||
service_node_proof_serialized() = default;
|
service_node_proof_serialized_old() = default;
|
||||||
service_node_proof_serialized(const service_nodes::proof_info &info)
|
service_node_proof_serialized_old(const service_nodes::proof_info &info)
|
||||||
: timestamp{native_to_little(info.timestamp)},
|
: timestamp{native_to_little(info.proof->timestamp)},
|
||||||
ip{native_to_little(info.public_ip)},
|
ip{native_to_little(info.proof->public_ip)},
|
||||||
storage_port{native_to_little(info.storage_port)},
|
storage_port{native_to_little(info.proof->storage_port)},
|
||||||
storage_lmq_port{native_to_little(info.storage_lmq_port)},
|
storage_lmq_port{native_to_little(info.proof->storage_lmq_port)},
|
||||||
quorumnet_port{native_to_little(info.quorumnet_port)},
|
quorumnet_port{native_to_little(info.proof->qnet_port)},
|
||||||
version{native_to_little(info.version[0]), native_to_little(info.version[1]), native_to_little(info.version[2])},
|
version{native_to_little_container(info.proof->version)},
|
||||||
pubkey_ed25519{info.pubkey_ed25519}
|
pubkey_ed25519{info.proof->pubkey_ed25519}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void update(service_nodes::proof_info &info) const
|
void update(service_nodes::proof_info &info) const
|
||||||
{
|
{
|
||||||
info.timestamp = little_to_native(timestamp);
|
info.proof->timestamp = little_to_native(timestamp);
|
||||||
if (info.timestamp > info.effective_timestamp)
|
if (info.proof->timestamp > info.effective_timestamp)
|
||||||
info.effective_timestamp = info.timestamp;
|
info.effective_timestamp = info.proof->timestamp;
|
||||||
info.public_ip = little_to_native(ip);
|
info.proof->public_ip = little_to_native(ip);
|
||||||
info.storage_port = little_to_native(storage_port);
|
info.proof->storage_port = little_to_native(storage_port);
|
||||||
info.storage_lmq_port = little_to_native(storage_lmq_port);
|
info.proof->storage_lmq_port = little_to_native(storage_lmq_port);
|
||||||
info.quorumnet_port = little_to_native(quorumnet_port);
|
info.proof->qnet_port = little_to_native(quorumnet_port);
|
||||||
for (size_t i = 0; i < info.version.size(); i++)
|
info.proof->version = little_to_native_container(version);
|
||||||
info.version[i] = little_to_native(version[i]);
|
info.proof->storage_server_version = {0, 0, 0};
|
||||||
|
info.proof->lokinet_version = {0, 0, 0};
|
||||||
info.update_pubkey(pubkey_ed25519);
|
info.update_pubkey(pubkey_ed25519);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator service_nodes::proof_info() const
|
operator service_nodes::proof_info() const
|
||||||
{
|
{
|
||||||
service_nodes::proof_info info{};
|
service_nodes::proof_info info{};
|
||||||
|
@ -6276,11 +6317,39 @@ struct service_node_proof_serialized
|
||||||
uint32_t ip;
|
uint32_t ip;
|
||||||
uint16_t storage_port;
|
uint16_t storage_port;
|
||||||
uint16_t quorumnet_port;
|
uint16_t quorumnet_port;
|
||||||
uint16_t version[3];
|
std::array<uint16_t, 3> version;
|
||||||
uint16_t storage_lmq_port;
|
uint16_t storage_lmq_port;
|
||||||
crypto::ed25519_public_key pubkey_ed25519;
|
crypto::ed25519_public_key pubkey_ed25519;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(service_node_proof_serialized) == 56, "service node serialization struct has unexpected size and/or padding");
|
static_assert(sizeof(service_node_proof_serialized_old) == 56, "service node serialization struct has unexpected size and/or padding");
|
||||||
|
|
||||||
|
struct service_node_proof_serialized : service_node_proof_serialized_old {
|
||||||
|
service_node_proof_serialized() = default;
|
||||||
|
service_node_proof_serialized(const service_nodes::proof_info &info)
|
||||||
|
: service_node_proof_serialized_old{info},
|
||||||
|
storage_server_version{native_to_little_container(info.proof->storage_server_version)},
|
||||||
|
lokinet_version{native_to_little_container(info.proof->lokinet_version)}
|
||||||
|
{}
|
||||||
|
std::array<uint16_t, 3> storage_server_version;
|
||||||
|
std::array<uint16_t, 3> lokinet_version;
|
||||||
|
char _padding[4];
|
||||||
|
|
||||||
|
void update(service_nodes::proof_info& info) const {
|
||||||
|
if (!info.proof) info.proof = std::unique_ptr<uptime_proof::Proof>(new uptime_proof::Proof());
|
||||||
|
service_node_proof_serialized_old::update(info);
|
||||||
|
info.proof->storage_server_version = little_to_native_container(storage_server_version);
|
||||||
|
info.proof->lokinet_version = little_to_native_container(lokinet_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator service_nodes::proof_info() const
|
||||||
|
{
|
||||||
|
service_nodes::proof_info info{};
|
||||||
|
update(info);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(service_node_proof_serialized) == 72, "service node serialization struct has unexpected size and/or padding");
|
||||||
|
|
||||||
bool BlockchainLMDB::get_service_node_proof(const crypto::public_key &pubkey, service_nodes::proof_info &proof) const
|
bool BlockchainLMDB::get_service_node_proof(const crypto::public_key &pubkey, service_nodes::proof_info &proof) const
|
||||||
{
|
{
|
||||||
|
@ -6298,7 +6367,11 @@ bool BlockchainLMDB::get_service_node_proof(const crypto::public_key &pubkey, se
|
||||||
else if (result != MDB_SUCCESS)
|
else if (result != MDB_SUCCESS)
|
||||||
throw0(DB_ERROR(lmdb_error("DB error attempting to get service node data", result)));
|
throw0(DB_ERROR(lmdb_error("DB error attempting to get service node data", result)));
|
||||||
|
|
||||||
static_cast<const service_node_proof_serialized *>(v.mv_data)->update(proof);
|
if (v.mv_size == sizeof(service_node_proof_serialized_old))
|
||||||
|
static_cast<const service_node_proof_serialized_old*>(v.mv_data)->update(proof);
|
||||||
|
else
|
||||||
|
static_cast<const service_node_proof_serialized*>(v.mv_data)->update(proof);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6328,8 +6401,13 @@ std::unordered_map<crypto::public_key, service_nodes::proof_info> BlockchainLMDB
|
||||||
RCURSOR(service_node_proofs);
|
RCURSOR(service_node_proofs);
|
||||||
|
|
||||||
std::unordered_map<crypto::public_key, service_nodes::proof_info> result;
|
std::unordered_map<crypto::public_key, service_nodes::proof_info> result;
|
||||||
for (const auto &pair : iterable_db<crypto::public_key, service_node_proof_serialized>(m_cursors->service_node_proofs))
|
for (const auto &pair : iterable_db<crypto::public_key, service_node_proof_serialized, service_node_proof_serialized_old>(
|
||||||
result.emplace(*pair.first, *pair.second);
|
m_cursors->service_node_proofs)) {
|
||||||
|
if (std::holds_alternative<service_node_proof_serialized*>(pair.second))
|
||||||
|
result.emplace(*pair.first, *var::get<service_node_proof_serialized*>(pair.second));
|
||||||
|
else
|
||||||
|
result.emplace(*pair.first, service_node_proof_serialized{*var::get<service_node_proof_serialized_old*>(pair.second)});
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "blockchain_objects.h"
|
#include "blockchain_objects.h"
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
#include "wallet/ringdb.h"
|
#include "wallet/ringdb.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "blockchain_objects.h"
|
#include "blockchain_objects.h"
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "blockchain_objects.h"
|
#include "blockchain_objects.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "blocks/blocks.h"
|
#include "blocks/blocks.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
#include "serialization/binary_utils.h"
|
#include "serialization/binary_utils.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "common/hex.h"
|
#include "common/hex.h"
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "epee/misc_os_dependent.h"
|
#include "epee/misc_os_dependent.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "blockchain_objects.h"
|
#include "blockchain_objects.h"
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -109,6 +110,19 @@ std::string copy_guts(const T& val) {
|
||||||
return std::string{view_guts(val)};
|
return std::string{view_guts(val)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function to reverse the above view_guts
|
||||||
|
template <typename T>
|
||||||
|
T make_from_guts(std::string_view s) {
|
||||||
|
static_assert((std::is_standard_layout_v<T> && std::has_unique_object_representations_v<T>)
|
||||||
|
|| epee::is_byte_spannable<T>,
|
||||||
|
"cannot safely reconstitute a non-trivial class from data");
|
||||||
|
if (s.size() != sizeof(T))
|
||||||
|
throw std::runtime_error("Cannot reconstitute type: wrong type content size");
|
||||||
|
T x;
|
||||||
|
std::memcpy(&x, s.data(), sizeof(T));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
std::string lowercase_ascii_string(std::string_view src);
|
std::string lowercase_ascii_string(std::string_view src);
|
||||||
|
|
||||||
/// Converts a duration into a human friendlier string.
|
/// Converts a duration into a human friendlier string.
|
||||||
|
|
|
@ -194,6 +194,7 @@ constexpr uint64_t BLOCKS_EXPECTED_IN_YEARS(int years) { return BLOCKS_EXPECTED_
|
||||||
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY cryptonote::network_version_16_pulse
|
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY cryptonote::network_version_16_pulse
|
||||||
#define HF_VERSION_PULSE cryptonote::network_version_16_pulse
|
#define HF_VERSION_PULSE cryptonote::network_version_16_pulse
|
||||||
#define HF_VERSION_CLSAG cryptonote::network_version_16_pulse
|
#define HF_VERSION_CLSAG cryptonote::network_version_16_pulse
|
||||||
|
#define HF_VERSION_PROOF_BTENC cryptonote::network_version_17
|
||||||
|
|
||||||
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ add_library(cryptonote_core
|
||||||
tx_pool.cpp
|
tx_pool.cpp
|
||||||
tx_sanity_check.cpp
|
tx_sanity_check.cpp
|
||||||
cryptonote_tx_utils.cpp
|
cryptonote_tx_utils.cpp
|
||||||
pulse.cpp)
|
pulse.cpp
|
||||||
|
uptime_proof.cpp)
|
||||||
|
|
||||||
target_link_libraries(cryptonote_core
|
target_link_libraries(cryptonote_core
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|
|
@ -49,6 +49,7 @@ extern "C" {
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#include "cryptonote_core.h"
|
#include "cryptonote_core.h"
|
||||||
|
#include "uptime_proof.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/sha256sum.h"
|
#include "common/sha256sum.h"
|
||||||
#include "common/threadpool.h"
|
#include "common/threadpool.h"
|
||||||
|
@ -1670,7 +1671,7 @@ namespace cryptonote
|
||||||
std::array<uint16_t,3> proofversion;
|
std::array<uint16_t,3> proofversion;
|
||||||
m_service_node_list.access_proof(pubkey, [&](auto &proof) {
|
m_service_node_list.access_proof(pubkey, [&](auto &proof) {
|
||||||
x_pkey = proof.pubkey_x25519;
|
x_pkey = proof.pubkey_x25519;
|
||||||
proofversion = proof.version;
|
proofversion = proof.proof->version;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (proofversion >= MIN_TIMESTAMP_VERSION && x_pkey) {
|
if (proofversion >= MIN_TIMESTAMP_VERSION && x_pkey) {
|
||||||
|
@ -1930,10 +1931,19 @@ namespace cryptonote
|
||||||
if (!m_service_node)
|
if (!m_service_node)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
cryptonote_connection_context fake_context{};
|
cryptonote_connection_context fake_context{};
|
||||||
bool relayed = get_protocol()->relay_uptime_proof(req, fake_context);
|
bool relayed;
|
||||||
|
auto height = get_current_blockchain_height();
|
||||||
|
auto hf_version = get_hard_fork_version(height);
|
||||||
|
//TODO: remove after HF17
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
NOTIFY_BTENCODED_UPTIME_PROOF::request req = proof.generate_request();
|
||||||
|
relayed = get_protocol()->relay_btencoded_uptime_proof(req, fake_context);
|
||||||
|
}
|
||||||
if (relayed)
|
if (relayed)
|
||||||
MGINFO("Submitted uptime-proof for Service Node (yours): " << m_service_keys.pub);
|
MGINFO("Submitted uptime-proof for Service Node (yours): " << m_service_keys.pub);
|
||||||
|
|
||||||
|
@ -1953,6 +1963,23 @@ namespace cryptonote
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
|
bool core::handle_btencoded_uptime_proof(const NOTIFY_BTENCODED_UPTIME_PROOF::request &req, bool &my_uptime_proof_confirmation)
|
||||||
|
{
|
||||||
|
crypto::x25519_public_key pkey = {};
|
||||||
|
auto proof = std::make_unique<uptime_proof::Proof>(req.proof);
|
||||||
|
proof->sig = tools::make_from_guts<crypto::signature>(req.sig);
|
||||||
|
proof->sig_ed25519 = tools::make_from_guts<crypto::ed25519_signature>(req.ed_sig);
|
||||||
|
auto pubkey = proof->pubkey;
|
||||||
|
bool result = m_service_node_list.handle_btencoded_uptime_proof(std::move(proof), my_uptime_proof_confirmation, pkey);
|
||||||
|
if (result && m_service_node_list.is_service_node(pubkey, true /*require_active*/) && pkey)
|
||||||
|
{
|
||||||
|
oxenmq::pubkey_set added;
|
||||||
|
added.insert(tools::copy_guts(pkey));
|
||||||
|
m_lmq->update_active_sns(added, {} /*removed*/);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------
|
||||||
crypto::hash core::on_transaction_relayed(const cryptonote::blobdata& tx_blob)
|
crypto::hash core::on_transaction_relayed(const cryptonote::blobdata& tx_blob)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
|
std::vector<std::pair<crypto::hash, cryptonote::blobdata>> txs;
|
||||||
|
@ -2301,12 +2328,12 @@ namespace cryptonote
|
||||||
sn_pks.push_back(sni.pubkey);
|
sn_pks.push_back(sni.pubkey);
|
||||||
|
|
||||||
m_service_node_list.for_each_service_node_info_and_proof(sn_pks.begin(), sn_pks.end(), [&](auto& pk, auto& sni, auto& proof) {
|
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.public_ip == m_sn_public_ip &&
|
if (pk != m_service_keys.pub && proof.proof->public_ip == m_sn_public_ip &&
|
||||||
(proof.quorumnet_port == m_quorumnet_port || proof.storage_port == m_storage_port || proof.storage_port == m_storage_lmq_port))
|
(proof.proof->qnet_port == m_quorumnet_port || proof.proof->storage_port == m_storage_port || proof.proof->storage_port == m_storage_lmq_port))
|
||||||
MGINFO_RED(
|
MGINFO_RED(
|
||||||
"Another service node (" << pk << ") is broadcasting the same public IP and ports as this service node (" <<
|
"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.quorumnet_port << "[qnet], :" <<
|
epee::string_tools::get_ip_string_from_int32(m_sn_public_ip) << ":" << proof.proof->qnet_port << "[qnet], :" <<
|
||||||
proof.storage_port << "[SS-HTTP], :" << proof.storage_lmq_port << "[SS-LMQ]). "
|
proof.proof->storage_port << "[SS-HTTP], :" << proof.proof->storage_lmq_port << "[SS-LMQ]). "
|
||||||
"This will lead to deregistration of one or both service nodes if not corrected. "
|
"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?)");
|
"(Do both service nodes have the correct IP for the service-node-public-ip setting?)");
|
||||||
});
|
});
|
||||||
|
|
|
@ -159,6 +159,15 @@ namespace cryptonote
|
||||||
*/
|
*/
|
||||||
bool handle_uptime_proof(const NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation);
|
bool handle_uptime_proof(const NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief handles an incoming uptime proof that is encoded using B-encoding
|
||||||
|
*
|
||||||
|
* Parses an incoming uptime proof
|
||||||
|
*
|
||||||
|
* @return true if we haven't seen it before and thus need to relay.
|
||||||
|
*/
|
||||||
|
bool handle_btencoded_uptime_proof(const NOTIFY_BTENCODED_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief handles an incoming transaction
|
* @brief handles an incoming transaction
|
||||||
*
|
*
|
||||||
|
@ -1163,6 +1172,10 @@ namespace cryptonote
|
||||||
std::unordered_map<crypto::x25519_public_key, oxenmq::AuthLevel>& _lmq_auth_level_map() { return m_lmq_auth; }
|
std::unordered_map<crypto::x25519_public_key, oxenmq::AuthLevel>& _lmq_auth_level_map() { return m_lmq_auth; }
|
||||||
oxenmq::TaggedThreadID const &pulse_thread_id() const { return *m_pulse_thread_id; }
|
oxenmq::TaggedThreadID const &pulse_thread_id() const { return *m_pulse_thread_id; }
|
||||||
|
|
||||||
|
/// Service Node's storage server and lokinet version
|
||||||
|
std::array<uint16_t, 3> ss_version;
|
||||||
|
std::array<uint16_t, 3> lokinet_version;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,6 +43,7 @@ extern "C" {
|
||||||
#include "cryptonote_tx_utils.h"
|
#include "cryptonote_tx_utils.h"
|
||||||
#include "cryptonote_basic/tx_extra.h"
|
#include "cryptonote_basic/tx_extra.h"
|
||||||
#include "cryptonote_basic/hardfork.h"
|
#include "cryptonote_basic/hardfork.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "epee/int-util.h"
|
#include "epee/int-util.h"
|
||||||
#include "common/scoped_message_writer.h"
|
#include "common/scoped_message_writer.h"
|
||||||
#include "common/i18n.h"
|
#include "common/i18n.h"
|
||||||
|
@ -56,8 +57,10 @@ extern "C" {
|
||||||
|
|
||||||
#include "pulse.h"
|
#include "pulse.h"
|
||||||
#include "service_node_list.h"
|
#include "service_node_list.h"
|
||||||
|
#include "uptime_proof.h"
|
||||||
#include "service_node_rules.h"
|
#include "service_node_rules.h"
|
||||||
#include "service_node_swarm.h"
|
#include "service_node_swarm.h"
|
||||||
|
#include <lokimq/bt_serialize.h>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
|
@ -2743,15 +2746,14 @@ namespace service_nodes
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static crypto::hash hash_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof, uint8_t hf_version)
|
//TODO: remove after HF17
|
||||||
|
crypto::hash service_node_list::hash_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof) const
|
||||||
{
|
{
|
||||||
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);
|
size_t buf_size;
|
||||||
size_t buf_size = buf.size();
|
|
||||||
|
|
||||||
if (hf_version < cryptonote::network_version_15_lns) // TODO - can be removed post-HF15
|
|
||||||
buf_size -= sizeof(proof.storage_lmq_port);
|
|
||||||
|
|
||||||
crypto::hash result;
|
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);
|
||||||
|
buf_size = buf.size();
|
||||||
crypto::cn_fast_hash(buf.data(), buf_size, result);
|
crypto::cn_fast_hash(buf.data(), buf_size, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2771,12 +2773,18 @@ namespace service_nodes
|
||||||
result.qnet_port = quorumnet_port;
|
result.qnet_port = quorumnet_port;
|
||||||
result.pubkey_ed25519 = keys.pub_ed25519;
|
result.pubkey_ed25519 = keys.pub_ed25519;
|
||||||
|
|
||||||
crypto::hash hash = hash_uptime_proof(result, m_blockchain.get_current_hard_fork_version());
|
crypto::hash hash = hash_uptime_proof(result);
|
||||||
crypto::generate_signature(hash, keys.pub, keys.key, result.sig);
|
crypto::generate_signature(hash, keys.pub, keys.key, result.sig);
|
||||||
crypto_sign_detached(result.sig_ed25519.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash.data), keys.key_ed25519.data);
|
crypto_sign_detached(result.sig_ed25519.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash.data), keys.key_ed25519.data);
|
||||||
return result;
|
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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cpp_lib_erase_if // # (C++20)
|
#ifdef __cpp_lib_erase_if // # (C++20)
|
||||||
using std::erase_if;
|
using std::erase_if;
|
||||||
#else
|
#else
|
||||||
|
@ -2800,13 +2808,48 @@ namespace service_nodes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proof_info::proof_info()
|
||||||
|
: proof(std::make_unique<uptime_proof::Proof>()) {};
|
||||||
|
|
||||||
void proof_info::store(const crypto::public_key &pubkey, cryptonote::Blockchain &blockchain)
|
void proof_info::store(const crypto::public_key &pubkey, cryptonote::Blockchain &blockchain)
|
||||||
{
|
{
|
||||||
|
if (!proof) proof = std::unique_ptr<uptime_proof::Proof>(new uptime_proof::Proof());
|
||||||
std::unique_lock lock{blockchain};
|
std::unique_lock lock{blockchain};
|
||||||
auto &db = blockchain.get_db();
|
auto &db = blockchain.get_db();
|
||||||
db.set_service_node_proof(pubkey, *this);
|
db.set_service_node_proof(pubkey, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool proof_info::update(uint64_t ts, std::unique_ptr<uptime_proof::Proof> new_proof, const crypto::x25519_public_key &pk_x2)
|
||||||
|
{
|
||||||
|
bool update_db = false;
|
||||||
|
if (!proof || *proof != *new_proof) {
|
||||||
|
update_db = true;
|
||||||
|
proof = std::move(new_proof);
|
||||||
|
}
|
||||||
|
update_db |= update_val(timestamp, ts);
|
||||||
|
effective_timestamp = proof->timestamp;
|
||||||
|
pubkey_x25519 = pk_x2;
|
||||||
|
|
||||||
|
// Track an IP change (so that the obligations quorum can penalize for IP changes)
|
||||||
|
// We only keep the two most recent because all we really care about is whether it had more than one
|
||||||
|
//
|
||||||
|
// If we already know about the IP, update its timestamp:
|
||||||
|
auto now = std::time(nullptr);
|
||||||
|
if (public_ips[0].first && public_ips[0].first == proof->public_ip)
|
||||||
|
public_ips[0].second = now;
|
||||||
|
else if (public_ips[1].first && public_ips[1].first == proof->public_ip)
|
||||||
|
public_ips[1].second = now;
|
||||||
|
// Otherwise replace whichever IP has the older timestamp
|
||||||
|
else if (public_ips[0].second > public_ips[1].second)
|
||||||
|
public_ips[1] = {proof->public_ip, now};
|
||||||
|
else
|
||||||
|
public_ips[0] = {proof->public_ip, now};
|
||||||
|
|
||||||
|
return update_db;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//TODO remove after HF17
|
||||||
bool proof_info::update(uint64_t ts,
|
bool proof_info::update(uint64_t ts,
|
||||||
uint32_t ip,
|
uint32_t ip,
|
||||||
uint16_t s_port,
|
uint16_t s_port,
|
||||||
|
@ -2817,14 +2860,15 @@ namespace service_nodes
|
||||||
const crypto::x25519_public_key& pk_x2)
|
const crypto::x25519_public_key& pk_x2)
|
||||||
{
|
{
|
||||||
bool update_db = false;
|
bool update_db = false;
|
||||||
|
if (!proof) proof = std::unique_ptr<uptime_proof::Proof>(new uptime_proof::Proof());
|
||||||
update_db |= update_val(timestamp, ts);
|
update_db |= update_val(timestamp, ts);
|
||||||
update_db |= update_val(public_ip, ip);
|
update_db |= update_val(proof->public_ip, ip);
|
||||||
update_db |= update_val(storage_port, s_port);
|
update_db |= update_val(proof->storage_port, s_port);
|
||||||
update_db |= update_val(storage_lmq_port, s_lmq_port);
|
update_db |= update_val(proof->storage_lmq_port, s_lmq_port);
|
||||||
update_db |= update_val(quorumnet_port, q_port);
|
update_db |= update_val(proof->qnet_port, q_port);
|
||||||
update_db |= update_val(version, ver);
|
update_db |= update_val(proof->version, ver);
|
||||||
update_db |= update_val(pubkey_ed25519, pk_ed);
|
update_db |= update_val(proof->pubkey_ed25519, pk_ed);
|
||||||
effective_timestamp = timestamp;
|
effective_timestamp = proof->timestamp;
|
||||||
pubkey_x25519 = pk_x2;
|
pubkey_x25519 = pk_x2;
|
||||||
|
|
||||||
// Track an IP change (so that the obligations quorum can penalize for IP changes)
|
// Track an IP change (so that the obligations quorum can penalize for IP changes)
|
||||||
|
@ -2832,33 +2876,34 @@ namespace service_nodes
|
||||||
//
|
//
|
||||||
// If we already know about the IP, update its timestamp:
|
// If we already know about the IP, update its timestamp:
|
||||||
auto now = std::time(nullptr);
|
auto now = std::time(nullptr);
|
||||||
if (public_ips[0].first && public_ips[0].first == public_ip)
|
if (public_ips[0].first && public_ips[0].first == proof->public_ip)
|
||||||
public_ips[0].second = now;
|
public_ips[0].second = now;
|
||||||
else if (public_ips[1].first && public_ips[1].first == public_ip)
|
else if (public_ips[1].first && public_ips[1].first == proof->public_ip)
|
||||||
public_ips[1].second = now;
|
public_ips[1].second = now;
|
||||||
// Otherwise replace whichever IP has the older timestamp
|
// Otherwise replace whichever IP has the older timestamp
|
||||||
else if (public_ips[0].second > public_ips[1].second)
|
else if (public_ips[0].second > public_ips[1].second)
|
||||||
public_ips[1] = {public_ip, now};
|
public_ips[1] = {proof->public_ip, now};
|
||||||
else
|
else
|
||||||
public_ips[0] = {public_ip, now};
|
public_ips[0] = {proof->public_ip, now};
|
||||||
|
|
||||||
return update_db;
|
return update_db;
|
||||||
};
|
};
|
||||||
|
|
||||||
void proof_info::update_pubkey(const crypto::ed25519_public_key &pk) {
|
void proof_info::update_pubkey(const crypto::ed25519_public_key &pk) {
|
||||||
if (pk == pubkey_ed25519)
|
if (pk == proof->pubkey_ed25519)
|
||||||
return;
|
return;
|
||||||
if (pk && 0 == crypto_sign_ed25519_pk_to_curve25519(pubkey_x25519.data, pk.data)) {
|
if (pk && 0 == crypto_sign_ed25519_pk_to_curve25519(pubkey_x25519.data, pk.data)) {
|
||||||
pubkey_ed25519 = pk;
|
proof->pubkey_ed25519 = pk;
|
||||||
} else {
|
} else {
|
||||||
MWARNING("Failed to derive x25519 pubkey from ed25519 pubkey " << pubkey_ed25519);
|
MWARNING("Failed to derive x25519 pubkey from ed25519 pubkey " << proof->pubkey_ed25519);
|
||||||
pubkey_x25519 = crypto::x25519_public_key::null();
|
pubkey_x25519 = crypto::x25519_public_key::null();
|
||||||
pubkey_ed25519 = crypto::ed25519_public_key::null();
|
proof->pubkey_ed25519 = crypto::ed25519_public_key::null();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REJECT_PROOF(log) do { LOG_PRINT_L2("Rejecting uptime proof from " << proof.pubkey << ": " log); return false; } while (0)
|
#define REJECT_PROOF(log) do { LOG_PRINT_L2("Rejecting uptime proof from " << proof.pubkey << ": " log); return false; } while (0)
|
||||||
|
|
||||||
|
//TODO remove after HF17
|
||||||
bool service_node_list::handle_uptime_proof(cryptonote::NOTIFY_UPTIME_PROOF::request const &proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey)
|
bool service_node_list::handle_uptime_proof(cryptonote::NOTIFY_UPTIME_PROOF::request const &proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey)
|
||||||
{
|
{
|
||||||
uint8_t const hf_version = m_blockchain.get_current_hard_fork_version();
|
uint8_t const hf_version = m_blockchain.get_current_hard_fork_version();
|
||||||
|
@ -2878,7 +2923,8 @@ namespace service_nodes
|
||||||
//
|
//
|
||||||
// Validate proof signature
|
// Validate proof signature
|
||||||
//
|
//
|
||||||
crypto::hash hash = hash_uptime_proof(proof, hf_version);
|
crypto::hash hash = hash_uptime_proof(proof);
|
||||||
|
|
||||||
|
|
||||||
if (!crypto::check_signature(hash, proof.pubkey, proof.sig))
|
if (!crypto::check_signature(hash, proof.pubkey, proof.sig))
|
||||||
REJECT_PROOF("signature validation failed");
|
REJECT_PROOF("signature validation failed");
|
||||||
|
@ -2904,6 +2950,7 @@ namespace service_nodes
|
||||||
|
|
||||||
auto &iproof = proofs[proof.pubkey];
|
auto &iproof = proofs[proof.pubkey];
|
||||||
|
|
||||||
|
|
||||||
if (iproof.timestamp >= now - (UPTIME_PROOF_FREQUENCY_IN_SECONDS / 2))
|
if (iproof.timestamp >= now - (UPTIME_PROOF_FREQUENCY_IN_SECONDS / 2))
|
||||||
REJECT_PROOF("already received one uptime proof for this node recently");
|
REJECT_PROOF("already received one uptime proof for this node recently");
|
||||||
|
|
||||||
|
@ -2945,6 +2992,97 @@ namespace service_nodes
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef REJECT_PROOF
|
||||||
|
#define REJECT_PROOF(log) do { LOG_PRINT_L2("Rejecting uptime proof from " << proof->pubkey << ": " log); return false; } while (0)
|
||||||
|
|
||||||
|
bool service_node_list::handle_btencoded_uptime_proof(std::unique_ptr<uptime_proof::Proof> proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey)
|
||||||
|
{
|
||||||
|
uint8_t const hf_version = m_blockchain.get_current_hard_fork_version();
|
||||||
|
uint64_t const now = time(nullptr);
|
||||||
|
|
||||||
|
// Validate proof version, timestamp range,
|
||||||
|
if ((proof->timestamp < now - UPTIME_PROOF_BUFFER_IN_SECONDS) || (proof->timestamp > now + UPTIME_PROOF_BUFFER_IN_SECONDS))
|
||||||
|
REJECT_PROOF("timestamp is too far from now");
|
||||||
|
|
||||||
|
for (auto const &min : MIN_UPTIME_PROOF_VERSIONS)
|
||||||
|
if (hf_version >= min.hardfork && proof->version < min.version)
|
||||||
|
REJECT_PROOF("v" << min.version[0] << "." << min.version[1] << "." << min.version[2] << "+ oxen version is required for v" << std::to_string(hf_version) << "+ network proofs");
|
||||||
|
|
||||||
|
if (!debug_allow_local_ips && !epee::net_utils::is_ip_public(proof->public_ip))
|
||||||
|
REJECT_PROOF("public_ip is not actually public");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate proof signature
|
||||||
|
//
|
||||||
|
crypto::hash hash = proof->hash_uptime_proof();
|
||||||
|
|
||||||
|
if (!crypto::check_signature(hash, proof->pubkey, proof->sig))
|
||||||
|
REJECT_PROOF("signature validation failed");
|
||||||
|
|
||||||
|
crypto::x25519_public_key derived_x25519_pubkey = crypto::x25519_public_key::null();
|
||||||
|
if (!proof->pubkey_ed25519)
|
||||||
|
REJECT_PROOF("required ed25519 auxiliary pubkey " << proof->pubkey_ed25519 << " not included in proof");
|
||||||
|
|
||||||
|
if (0 != crypto_sign_verify_detached(proof->sig_ed25519.data, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash.data), proof->pubkey_ed25519.data))
|
||||||
|
REJECT_PROOF("ed25519 signature validation failed");
|
||||||
|
|
||||||
|
if (0 != crypto_sign_ed25519_pk_to_curve25519(derived_x25519_pubkey.data, proof->pubkey_ed25519.data)
|
||||||
|
|| !derived_x25519_pubkey)
|
||||||
|
REJECT_PROOF("invalid ed25519 pubkey included in proof (x25519 derivation failed)");
|
||||||
|
|
||||||
|
if (proof->qnet_port == 0)
|
||||||
|
REJECT_PROOF("invalid quorumnet port in uptime proof");
|
||||||
|
|
||||||
|
auto locks = tools::unique_locks(m_blockchain, m_sn_mutex, m_x25519_map_mutex);
|
||||||
|
auto it = m_state.service_nodes_infos.find(proof->pubkey);
|
||||||
|
if (it == m_state.service_nodes_infos.end())
|
||||||
|
REJECT_PROOF("no such service node is currently registered");
|
||||||
|
|
||||||
|
auto &iproof = proofs[proof->pubkey];
|
||||||
|
|
||||||
|
if (iproof.timestamp >= now - (UPTIME_PROOF_FREQUENCY_IN_SECONDS / 2))
|
||||||
|
REJECT_PROOF("already received one uptime proof for this node recently");
|
||||||
|
|
||||||
|
if (m_service_node_keys && proof->pubkey == m_service_node_keys->pub)
|
||||||
|
{
|
||||||
|
my_uptime_proof_confirmation = true;
|
||||||
|
MGINFO("Received uptime-proof confirmation back from network for Service Node (yours): " << proof->pubkey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_uptime_proof_confirmation = false;
|
||||||
|
LOG_PRINT_L2("Accepted uptime proof from " << proof->pubkey);
|
||||||
|
|
||||||
|
if (m_service_node_keys && proof->pubkey_ed25519 == m_service_node_keys->pub_ed25519)
|
||||||
|
MGINFO_RED("Uptime proof from SN " << proof->pubkey << " is not us, but is using our ed/x25519 keys; "
|
||||||
|
"this is likely to lead to deregistration of one or both service nodes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto old_x25519 = iproof.pubkey_x25519;
|
||||||
|
if (iproof.update(now, std::move(proof), derived_x25519_pubkey))
|
||||||
|
{
|
||||||
|
iproof.store(iproof.proof->pubkey, m_blockchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uint64_t) x25519_map_last_pruned + X25519_MAP_PRUNING_INTERVAL <= now)
|
||||||
|
{
|
||||||
|
time_t cutoff = now - X25519_MAP_PRUNING_LAG;
|
||||||
|
erase_if(x25519_to_pub, [&cutoff](const decltype(x25519_to_pub)::value_type &x) { return x.second.second < cutoff; });
|
||||||
|
x25519_map_last_pruned = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_x25519 && old_x25519 != derived_x25519_pubkey)
|
||||||
|
x25519_to_pub.erase(old_x25519);
|
||||||
|
|
||||||
|
if (derived_x25519_pubkey)
|
||||||
|
x25519_to_pub[derived_x25519_pubkey] = {iproof.proof->pubkey, now};
|
||||||
|
|
||||||
|
if (derived_x25519_pubkey && (old_x25519 != derived_x25519_pubkey))
|
||||||
|
x25519_pkey = derived_x25519_pubkey;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void service_node_list::cleanup_proofs()
|
void service_node_list::cleanup_proofs()
|
||||||
{
|
{
|
||||||
MDEBUG("Cleaning up expired SN proofs");
|
MDEBUG("Cleaning up expired SN proofs");
|
||||||
|
@ -3018,8 +3156,8 @@ namespace service_nodes
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
for_each_service_node_info_and_proof(&pubkey, &pubkey + 1, [&](auto&, auto&, auto& proof) {
|
for_each_service_node_info_and_proof(&pubkey, &pubkey + 1, [&](auto&, auto&, auto& proof) {
|
||||||
found = true;
|
found = true;
|
||||||
ip = proof.public_ip;
|
ip = proof.proof->public_ip;
|
||||||
port = proof.quorumnet_port;
|
port = proof.proof->qnet_port;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#include "cryptonote_core/service_node_quorum_cop.h"
|
#include "cryptonote_core/service_node_quorum_cop.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
|
#include <lokimq/bt_serialize.h>
|
||||||
|
|
||||||
namespace cryptonote
|
namespace cryptonote
|
||||||
{
|
{
|
||||||
class Blockchain;
|
class Blockchain;
|
||||||
|
@ -45,6 +47,11 @@ class BlockchainDB;
|
||||||
struct checkpoint_t;
|
struct checkpoint_t;
|
||||||
}; // namespace cryptonote
|
}; // namespace cryptonote
|
||||||
|
|
||||||
|
namespace uptime_proof
|
||||||
|
{
|
||||||
|
class Proof;
|
||||||
|
}
|
||||||
|
|
||||||
namespace service_nodes
|
namespace service_nodes
|
||||||
{
|
{
|
||||||
constexpr uint64_t INVALID_HEIGHT = static_cast<uint64_t>(-1);
|
constexpr uint64_t INVALID_HEIGHT = static_cast<uint64_t>(-1);
|
||||||
|
@ -136,6 +143,8 @@ namespace service_nodes
|
||||||
|
|
||||||
struct proof_info
|
struct proof_info
|
||||||
{
|
{
|
||||||
|
proof_info();
|
||||||
|
|
||||||
participation_history<participation_entry> pulse_participation{};
|
participation_history<participation_entry> pulse_participation{};
|
||||||
participation_history<participation_entry> checkpoint_participation{};
|
participation_history<participation_entry> checkpoint_participation{};
|
||||||
participation_history<timestamp_participation_entry> timestamp_participation{};
|
participation_history<timestamp_participation_entry> timestamp_participation{};
|
||||||
|
@ -149,12 +158,7 @@ namespace service_nodes
|
||||||
uint64_t storage_server_reachable_timestamp = 0;
|
uint64_t storage_server_reachable_timestamp = 0;
|
||||||
|
|
||||||
// Unlike all of the above (except for timestamp), these values *do* get serialized
|
// Unlike all of the above (except for timestamp), these values *do* get serialized
|
||||||
uint32_t public_ip = 0;
|
std::unique_ptr<uptime_proof::Proof> proof;
|
||||||
uint16_t storage_port = 0;
|
|
||||||
uint16_t storage_lmq_port = 0;
|
|
||||||
uint16_t quorumnet_port = 0;
|
|
||||||
std::array<uint16_t, 3> version{{0,0,0}};
|
|
||||||
crypto::ed25519_public_key pubkey_ed25519 = crypto::ed25519_public_key::null();
|
|
||||||
|
|
||||||
// Derived from pubkey_ed25519, not serialized
|
// Derived from pubkey_ed25519, not serialized
|
||||||
crypto::x25519_public_key pubkey_x25519 = crypto::x25519_public_key::null();
|
crypto::x25519_public_key pubkey_x25519 = crypto::x25519_public_key::null();
|
||||||
|
@ -168,6 +172,8 @@ namespace service_nodes
|
||||||
// Returns true if serializable data is changed (in which case `store()` should be called).
|
// Returns true if serializable data is changed (in which case `store()` should be called).
|
||||||
// Note that this does not update the m_x25519_to_pub map if the x25519 key changes (that's the
|
// Note that this does not update the m_x25519_to_pub map if the x25519 key changes (that's the
|
||||||
// caller's responsibility).
|
// 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 HF 17
|
||||||
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_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);
|
||||||
|
|
||||||
// Stores this record in the database.
|
// Stores this record in the database.
|
||||||
|
@ -511,13 +517,23 @@ namespace service_nodes
|
||||||
void set_quorum_history_storage(uint64_t hist_size); // 0 = none (default), 1 = unlimited, N = # of blocks
|
void set_quorum_history_storage(uint64_t hist_size); // 0 = none (default), 1 = unlimited, N = # of blocks
|
||||||
bool store();
|
bool store();
|
||||||
|
|
||||||
|
//TODO: remove after HF17
|
||||||
|
crypto::hash hash_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof) const;
|
||||||
|
|
||||||
/// Record public ip and storage port and add them to the service node list
|
/// Record public ip and storage port and add them to the service node list
|
||||||
|
//TODO: remove after HF17
|
||||||
cryptonote::NOTIFY_UPTIME_PROOF::request generate_uptime_proof(uint32_t public_ip,
|
cryptonote::NOTIFY_UPTIME_PROOF::request generate_uptime_proof(uint32_t public_ip,
|
||||||
uint16_t storage_port,
|
uint16_t storage_port,
|
||||||
uint16_t storage_lmq_port,
|
uint16_t storage_lmq_port,
|
||||||
uint16_t quorumnet_port) const;
|
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;
|
||||||
|
|
||||||
|
//TODO: remove after HF17
|
||||||
bool handle_uptime_proof(cryptonote::NOTIFY_UPTIME_PROOF::request const &proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey);
|
bool handle_uptime_proof(cryptonote::NOTIFY_UPTIME_PROOF::request const &proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey);
|
||||||
|
|
||||||
|
bool handle_btencoded_uptime_proof(std::unique_ptr<uptime_proof::Proof> proof, bool &my_uptime_proof_confirmation, crypto::x25519_public_key &x25519_pkey);
|
||||||
|
|
||||||
void record_checkpoint_participation(crypto::public_key const &pubkey, uint64_t height, bool participated);
|
void record_checkpoint_participation(crypto::public_key const &pubkey, uint64_t height, bool participated);
|
||||||
|
|
||||||
// Called every hour to remove proofs for expired SNs from memory and the database.
|
// Called every hour to remove proofs for expired SNs from memory and the database.
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "service_node_quorum_cop.h"
|
#include "service_node_quorum_cop.h"
|
||||||
#include "service_node_voting.h"
|
#include "service_node_voting.h"
|
||||||
#include "service_node_list.h"
|
#include "service_node_list.h"
|
||||||
|
#include "uptime_proof.h"
|
||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
#include "cryptonote_core.h"
|
#include "cryptonote_core.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -98,13 +99,13 @@ namespace service_nodes
|
||||||
|
|
||||||
m_core.get_service_node_list().access_proof(pubkey, [&](const proof_info &proof) {
|
m_core.get_service_node_list().access_proof(pubkey, [&](const proof_info &proof) {
|
||||||
ss_reachable = proof.storage_server_reachable;
|
ss_reachable = proof.storage_server_reachable;
|
||||||
timestamp = std::max(proof.timestamp, proof.effective_timestamp);
|
timestamp = std::max(proof.proof->timestamp, proof.effective_timestamp);
|
||||||
ips = proof.public_ips;
|
ips = proof.public_ips;
|
||||||
checkpoint_participation = proof.checkpoint_participation;
|
checkpoint_participation = proof.checkpoint_participation;
|
||||||
pulse_participation = proof.pulse_participation;
|
pulse_participation = proof.pulse_participation;
|
||||||
|
|
||||||
// TODO: remove after HF17
|
// TODO: remove after HF17
|
||||||
if (proof.version >= MIN_TIMESTAMP_VERSION && hf_version >= cryptonote::network_version_17) {
|
if (proof.proof->version >= MIN_TIMESTAMP_VERSION && hf_version >= cryptonote::network_version_17) {
|
||||||
timestamp_participation = proof.timestamp_participation;
|
timestamp_participation = proof.timestamp_participation;
|
||||||
timesync_status = proof.timesync_status;
|
timesync_status = proof.timesync_status;
|
||||||
check_timestamp_obligation = true;
|
check_timestamp_obligation = true;
|
||||||
|
|
|
@ -213,8 +213,8 @@ namespace service_nodes {
|
||||||
// blocks out of sync and sending something that it thinks is legit.
|
// blocks out of sync and sending something that it thinks is legit.
|
||||||
constexpr uint64_t VOTE_OR_TX_VERIFY_HEIGHT_BUFFER = 5;
|
constexpr uint64_t VOTE_OR_TX_VERIFY_HEIGHT_BUFFER = 5;
|
||||||
|
|
||||||
constexpr std::array<int, 3> MIN_STORAGE_SERVER_VERSION{{2, 0, 7}};
|
constexpr std::array<uint16_t, 3> MIN_STORAGE_SERVER_VERSION{{2, 0, 7}};
|
||||||
constexpr std::array<int, 3> MIN_LOKINET_VERSION{{0, 8, 0}};
|
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
|
// The minimum accepted version number, broadcasted by Service Nodes via uptime proofs for each hardfork
|
||||||
struct proof_version
|
struct proof_version
|
||||||
|
@ -224,6 +224,7 @@ namespace service_nodes {
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr proof_version MIN_UPTIME_PROOF_VERSIONS[] = {
|
constexpr proof_version MIN_UPTIME_PROOF_VERSIONS[] = {
|
||||||
|
{cryptonote::network_version_17, {9,0,0}},
|
||||||
{cryptonote::network_version_16_pulse, {8,1,0}},
|
{cryptonote::network_version_16_pulse, {8,1,0}},
|
||||||
{cryptonote::network_version_15_lns, {7,1,2}},
|
{cryptonote::network_version_15_lns, {7,1,2}},
|
||||||
{cryptonote::network_version_14_blink, {6,1,0}},
|
{cryptonote::network_version_14_blink, {6,1,0}},
|
||||||
|
|
154
src/cryptonote_core/uptime_proof.cpp
Normal file
154
src/cryptonote_core/uptime_proof.cpp
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
#include "uptime_proof.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <sodium/crypto_sign.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||||
|
#define OXEN_DEFAULT_LOG_CATEGORY "uptime_proof"
|
||||||
|
|
||||||
|
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}
|
||||||
|
{
|
||||||
|
this->lokinet_version = lokinet_version;
|
||||||
|
crypto::hash hash = this->hash_uptime_proof();
|
||||||
|
|
||||||
|
crypto::generate_signature(hash, keys.pub, keys.key, sig);
|
||||||
|
crypto_sign_detached(sig_ed25519.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash.data), keys.key_ed25519.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Deserialize from a btencoded string into our Proof instance
|
||||||
|
Proof::Proof(const std::string& serialized_proof)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const lokimq::bt_dict bt_proof = lokimq::bt_deserialize<lokimq::bt_dict>(serialized_proof);
|
||||||
|
//snode_version <X,X,X>
|
||||||
|
const lokimq::bt_list& bt_version = var::get<lokimq::bt_list>(bt_proof.at("v"));
|
||||||
|
int k = 0;
|
||||||
|
for (lokimq::bt_value const &i: bt_version){
|
||||||
|
version[k++] = static_cast<uint16_t>(lokimq::get_int<unsigned>(i));
|
||||||
|
}
|
||||||
|
//timestamp
|
||||||
|
timestamp = lokimq::get_int<unsigned>(bt_proof.at("t"));
|
||||||
|
//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>(lokimq::get_int<unsigned>(bt_proof.at("s")));
|
||||||
|
//pubkey_ed25519
|
||||||
|
pubkey_ed25519 = tools::make_from_guts<crypto::ed25519_public_key>(var::get<std::string>(bt_proof.at("pke")));
|
||||||
|
//pubkey
|
||||||
|
if (auto it = bt_proof.find("pk"); it != bt_proof.end())
|
||||||
|
pubkey = tools::make_from_guts<crypto::public_key>(var::get<std::string>(bt_proof.at("pk")));
|
||||||
|
else
|
||||||
|
std::memcpy(pubkey.data, pubkey_ed25519.data, 32);
|
||||||
|
//qnet_port
|
||||||
|
qnet_port = lokimq::get_int<unsigned>(bt_proof.at("q"));
|
||||||
|
//storage_lmq_port
|
||||||
|
storage_lmq_port = lokimq::get_int<unsigned>(bt_proof.at("slp"));
|
||||||
|
//storage_version
|
||||||
|
const lokimq::bt_list& bt_storage_version = var::get<lokimq::bt_list>(bt_proof.at("sv"));
|
||||||
|
k = 0;
|
||||||
|
for (lokimq::bt_value const &i: bt_storage_version){
|
||||||
|
storage_server_version[k++] = static_cast<uint16_t>(lokimq::get_int<unsigned>(i));
|
||||||
|
}
|
||||||
|
//lokinet_version
|
||||||
|
const lokimq::bt_list& bt_lokinet_version = var::get<lokimq::bt_list>(bt_proof.at("lv"));
|
||||||
|
k = 0;
|
||||||
|
for (lokimq::bt_value const &i: bt_lokinet_version){
|
||||||
|
lokinet_version[k++] = static_cast<uint16_t>(lokimq::get_int<unsigned>(i));
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
MWARNING("deserialization failed: " << e.what());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
crypto::hash Proof::hash_uptime_proof() const
|
||||||
|
{
|
||||||
|
crypto::hash result;
|
||||||
|
|
||||||
|
std::string serialized_proof = lokimq::bt_serialize(bt_encode_uptime_proof());
|
||||||
|
size_t buf_size = serialized_proof.size();
|
||||||
|
crypto::cn_fast_hash(serialized_proof.data(), buf_size, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
lokimq::bt_dict Proof::bt_encode_uptime_proof() const
|
||||||
|
{
|
||||||
|
lokimq::bt_dict encoded_proof{
|
||||||
|
//version
|
||||||
|
{"v", lokimq::bt_list{{version[0], version[1], version[2]}}},
|
||||||
|
//timestamp
|
||||||
|
{"t", timestamp},
|
||||||
|
//public_ip
|
||||||
|
{"ip", epee::string_tools::get_ip_string_from_int32(public_ip)},
|
||||||
|
//storage_port
|
||||||
|
{"s", storage_port},
|
||||||
|
//pubkey_ed25519
|
||||||
|
{"pke", tools::view_guts(pubkey_ed25519)},
|
||||||
|
//qnet_port
|
||||||
|
{"q", qnet_port},
|
||||||
|
//storage_lmq_port
|
||||||
|
{"slp", storage_lmq_port},
|
||||||
|
//storage_version
|
||||||
|
{"sv", lokimq::bt_list{{storage_server_version[0], storage_server_version[1], storage_server_version[2]}}},
|
||||||
|
//lokinet_version
|
||||||
|
{"lv", lokimq::bt_list{{lokinet_version[0], lokinet_version[1], lokinet_version[2]}}},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pubkey != pubkey_ed25519) encoded_proof["pk"] = tools::view_guts(pubkey);
|
||||||
|
|
||||||
|
return encoded_proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request Proof::generate_request() const
|
||||||
|
{
|
||||||
|
cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request request;
|
||||||
|
request.proof = lokimq::bt_serialize(this->bt_encode_uptime_proof());
|
||||||
|
request.sig = tools::view_guts(this->sig);
|
||||||
|
request.ed_sig = tools::view_guts(this->sig_ed25519);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const uptime_proof::Proof& lhs, const uptime_proof::Proof& rhs)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if( (lhs.timestamp != rhs.timestamp) ||
|
||||||
|
(lhs.pubkey != rhs.pubkey) ||
|
||||||
|
(lhs.sig != rhs.sig) ||
|
||||||
|
(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.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]))
|
||||||
|
result = false;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const uptime_proof::Proof& lhs, const uptime_proof::Proof& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
41
src/cryptonote_core/uptime_proof.h
Normal file
41
src/cryptonote_core/uptime_proof.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "service_node_list.h"
|
||||||
|
#include "../cryptonote_protocol/cryptonote_protocol_defs.h"
|
||||||
|
#include <lokimq/lokimq.h>
|
||||||
|
|
||||||
|
namespace uptime_proof
|
||||||
|
{
|
||||||
|
|
||||||
|
class Proof
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::array<uint16_t, 3> version;
|
||||||
|
std::array<uint16_t, 3> storage_server_version;
|
||||||
|
std::array<uint16_t, 3> lokinet_version;
|
||||||
|
|
||||||
|
uint64_t timestamp;
|
||||||
|
crypto::public_key pubkey;
|
||||||
|
crypto::signature sig;
|
||||||
|
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 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(const std::string& serialized_proof);
|
||||||
|
lokimq::bt_dict bt_encode_uptime_proof() const;
|
||||||
|
|
||||||
|
crypto::hash hash_uptime_proof() const;
|
||||||
|
|
||||||
|
cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request generate_request() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
bool operator==(const uptime_proof::Proof& lhs, const uptime_proof::Proof& rhs);
|
||||||
|
bool operator!=(const uptime_proof::Proof& lhs, const uptime_proof::Proof& rhs);
|
|
@ -119,6 +119,13 @@ KV_SERIALIZE_MAP_CODE_BEGIN(NOTIFY_UPTIME_PROOF::request)
|
||||||
KV_SERIALIZE_VAL_POD_AS_BLOB(sig_ed25519)
|
KV_SERIALIZE_VAL_POD_AS_BLOB(sig_ed25519)
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
KV_SERIALIZE_MAP_CODE_END()
|
||||||
|
|
||||||
|
KV_SERIALIZE_MAP_CODE_BEGIN(NOTIFY_BTENCODED_UPTIME_PROOF::request)
|
||||||
|
KV_SERIALIZE(proof)
|
||||||
|
KV_SERIALIZE(sig)
|
||||||
|
KV_SERIALIZE(ed_sig)
|
||||||
|
KV_SERIALIZE_MAP_CODE_END()
|
||||||
|
|
||||||
|
|
||||||
KV_SERIALIZE_MAP_CODE_BEGIN(NOTIFY_REQUEST_BLOCK_BLINKS::request)
|
KV_SERIALIZE_MAP_CODE_BEGIN(NOTIFY_REQUEST_BLOCK_BLINKS::request)
|
||||||
KV_SERIALIZE(heights)
|
KV_SERIALIZE(heights)
|
||||||
KV_SERIALIZE_MAP_CODE_END()
|
KV_SERIALIZE_MAP_CODE_END()
|
||||||
|
|
|
@ -267,6 +267,25 @@ namespace cryptonote
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* */
|
||||||
|
/************************************************************************/
|
||||||
|
struct NOTIFY_BTENCODED_UPTIME_PROOF
|
||||||
|
{
|
||||||
|
const static int ID = BC_COMMANDS_POOL_BASE + 12;
|
||||||
|
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
|
||||||
|
// BT-Encoded string of the Uptime Proof
|
||||||
|
std::string proof;
|
||||||
|
std::string sig;
|
||||||
|
std::string ed_sig;
|
||||||
|
|
||||||
|
KV_MAP_SERIALIZABLE
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace cryptonote
|
||||||
HANDLE_NOTIFY_T2(NOTIFY_NEW_FLUFFY_BLOCK, handle_notify_new_fluffy_block)
|
HANDLE_NOTIFY_T2(NOTIFY_NEW_FLUFFY_BLOCK, handle_notify_new_fluffy_block)
|
||||||
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_FLUFFY_MISSING_TX, handle_request_fluffy_missing_tx)
|
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_FLUFFY_MISSING_TX, handle_request_fluffy_missing_tx)
|
||||||
HANDLE_NOTIFY_T2(NOTIFY_UPTIME_PROOF, handle_uptime_proof)
|
HANDLE_NOTIFY_T2(NOTIFY_UPTIME_PROOF, handle_uptime_proof)
|
||||||
|
HANDLE_NOTIFY_T2(NOTIFY_BTENCODED_UPTIME_PROOF, handle_btencoded_uptime_proof)
|
||||||
HANDLE_NOTIFY_T2(NOTIFY_NEW_SERVICE_NODE_VOTE, handle_notify_new_service_node_vote)
|
HANDLE_NOTIFY_T2(NOTIFY_NEW_SERVICE_NODE_VOTE, handle_notify_new_service_node_vote)
|
||||||
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_BLOCK_BLINKS, handle_request_block_blinks)
|
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_BLOCK_BLINKS, handle_request_block_blinks)
|
||||||
HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_BLOCK_BLINKS, handle_response_block_blinks)
|
HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_BLOCK_BLINKS, handle_response_block_blinks)
|
||||||
|
@ -118,6 +119,7 @@ namespace cryptonote
|
||||||
int handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context);
|
int handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context);
|
||||||
int handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context);
|
int handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context);
|
||||||
int handle_uptime_proof(int command, NOTIFY_UPTIME_PROOF::request& arg, cryptonote_connection_context& context);
|
int handle_uptime_proof(int command, NOTIFY_UPTIME_PROOF::request& arg, cryptonote_connection_context& context);
|
||||||
|
int handle_btencoded_uptime_proof(int command, NOTIFY_BTENCODED_UPTIME_PROOF::request& arg, cryptonote_connection_context& context);
|
||||||
int handle_notify_new_service_node_vote(int command, NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& context);
|
int handle_notify_new_service_node_vote(int command, NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& context);
|
||||||
int handle_request_block_blinks(int command, NOTIFY_REQUEST_BLOCK_BLINKS::request& arg, cryptonote_connection_context& context);
|
int handle_request_block_blinks(int command, NOTIFY_REQUEST_BLOCK_BLINKS::request& arg, cryptonote_connection_context& context);
|
||||||
int handle_response_block_blinks(int command, NOTIFY_RESPONSE_BLOCK_BLINKS::request& arg, cryptonote_connection_context& context);
|
int handle_response_block_blinks(int command, NOTIFY_RESPONSE_BLOCK_BLINKS::request& arg, cryptonote_connection_context& context);
|
||||||
|
@ -152,6 +154,7 @@ namespace cryptonote
|
||||||
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context);
|
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context);
|
||||||
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context);
|
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context);
|
||||||
virtual bool relay_uptime_proof(NOTIFY_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context);
|
virtual bool relay_uptime_proof(NOTIFY_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context);
|
||||||
|
virtual bool relay_btencoded_uptime_proof(NOTIFY_BTENCODED_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context);
|
||||||
virtual bool relay_service_node_votes(NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& exclude_context);
|
virtual bool relay_service_node_votes(NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& exclude_context);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//bool get_payload_sync_data(HANDSHAKE_DATA::request& hshd, cryptonote_connection_context& context);
|
//bool get_payload_sync_data(HANDSHAKE_DATA::request& hshd, cryptonote_connection_context& context);
|
||||||
|
|
|
@ -876,6 +876,39 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<class t_core>
|
||||||
|
int t_cryptonote_protocol_handler<t_core>::handle_btencoded_uptime_proof(int command, NOTIFY_BTENCODED_UPTIME_PROOF::request& arg, cryptonote_connection_context& context)
|
||||||
|
{
|
||||||
|
MLOG_P2P_MESSAGE("Received NOTIFY_BTENCODED_UPTIME_PROOF");
|
||||||
|
// NOTE: Don't relay your own uptime proof, otherwise we have the following situation
|
||||||
|
|
||||||
|
// Node1 sends uptime ->
|
||||||
|
// Node2 receives uptime and relays it back to Node1 for acknowledgement ->
|
||||||
|
// Node1 receives it, handle_uptime_proof returns true to acknowledge, Node1 tries to resend to the same peers again
|
||||||
|
|
||||||
|
// Instead, if we receive our own uptime proof, then acknowledge but don't
|
||||||
|
// send on. If the we are missing an uptime proof it will have been
|
||||||
|
// submitted automatically by the daemon itself instead of
|
||||||
|
// using my own proof relayed by other nodes.
|
||||||
|
|
||||||
|
(void)context;
|
||||||
|
bool my_uptime_proof_confirmation = false;
|
||||||
|
|
||||||
|
if (m_core.handle_btencoded_uptime_proof(arg, my_uptime_proof_confirmation))
|
||||||
|
{
|
||||||
|
if (!my_uptime_proof_confirmation)
|
||||||
|
{
|
||||||
|
// NOTE: The default exclude context contains the peer who sent us this
|
||||||
|
// uptime proof, we want to ensure we relay it back so they know that the
|
||||||
|
// peer they relayed to received their uptime and confirm it, so send in an
|
||||||
|
// empty context so we don't omit the source peer from the relay back.
|
||||||
|
cryptonote_connection_context empty_context = {};
|
||||||
|
relay_btencoded_uptime_proof(arg, empty_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
template<class t_core>
|
template<class t_core>
|
||||||
|
@ -2526,6 +2559,13 @@ skip:
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
template<class t_core>
|
template<class t_core>
|
||||||
|
bool t_cryptonote_protocol_handler<t_core>::relay_btencoded_uptime_proof(NOTIFY_BTENCODED_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context)
|
||||||
|
{
|
||||||
|
bool result = relay_to_synchronized_peers<NOTIFY_BTENCODED_UPTIME_PROOF>(arg, exclude_context);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<class t_core>
|
||||||
bool t_cryptonote_protocol_handler<t_core>::relay_service_node_votes(NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& exclude_context)
|
bool t_cryptonote_protocol_handler<t_core>::relay_service_node_votes(NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& exclude_context)
|
||||||
{
|
{
|
||||||
bool result = relay_to_synchronized_peers<NOTIFY_NEW_SERVICE_NODE_VOTE>(arg, exclude_context);
|
bool result = relay_to_synchronized_peers<NOTIFY_NEW_SERVICE_NODE_VOTE>(arg, exclude_context);
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace cryptonote
|
||||||
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context)=0;
|
virtual bool relay_block(NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& exclude_context)=0;
|
||||||
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context)=0;
|
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context)=0;
|
||||||
virtual bool relay_uptime_proof(NOTIFY_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context)=0;
|
virtual bool relay_uptime_proof(NOTIFY_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context)=0;
|
||||||
|
virtual bool relay_btencoded_uptime_proof(NOTIFY_BTENCODED_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context)=0;
|
||||||
//virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)=0;
|
//virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)=0;
|
||||||
virtual bool relay_service_node_votes(NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& exclude_context)=0;
|
virtual bool relay_service_node_votes(NOTIFY_NEW_SERVICE_NODE_VOTE::request& arg, cryptonote_connection_context& exclude_context)=0;
|
||||||
};
|
};
|
||||||
|
@ -68,5 +69,9 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
virtual bool relay_btencoded_uptime_proof(NOTIFY_BTENCODED_UPTIME_PROOF::request& arg, cryptonote_connection_context& exclude_context)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "cryptonote_core/tx_blink.h"
|
#include "cryptonote_core/tx_blink.h"
|
||||||
#include "cryptonote_core/tx_pool.h"
|
#include "cryptonote_core/tx_pool.h"
|
||||||
#include "cryptonote_core/pulse.h"
|
#include "cryptonote_core/pulse.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "quorumnet_conn_matrix.h"
|
#include "quorumnet_conn_matrix.h"
|
||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
#include "common/random.h"
|
#include "common/random.h"
|
||||||
|
@ -160,7 +161,7 @@ peer_prepare_relay_to_quorum_subset(cryptonote::core &core, It quorum_begin, It
|
||||||
|
|
||||||
MDEBUG("Have " << candidates.size() << " SN candidates");
|
MDEBUG("Have " << candidates.size() << " SN candidates");
|
||||||
|
|
||||||
std::vector<std::tuple<std::string, std::string, decltype(proof_info{}.version)>> remotes; // {x25519 pubkey, connect string, version}
|
std::vector<std::tuple<std::string, std::string, decltype(proof_info{}.proof->version)>> remotes; // {x25519 pubkey, connect string, version}
|
||||||
remotes.reserve(candidates.size());
|
remotes.reserve(candidates.size());
|
||||||
core.get_service_node_list().for_each_service_node_info_and_proof(candidates.begin(), candidates.end(),
|
core.get_service_node_list().for_each_service_node_info_and_proof(candidates.begin(), candidates.end(),
|
||||||
[&remotes](const auto &pubkey, const auto &info, const auto &proof) {
|
[&remotes](const auto &pubkey, const auto &info, const auto &proof) {
|
||||||
|
@ -168,14 +169,14 @@ peer_prepare_relay_to_quorum_subset(cryptonote::core &core, It quorum_begin, It
|
||||||
MTRACE("Not include inactive node " << pubkey);
|
MTRACE("Not include inactive node " << pubkey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!proof.pubkey_x25519 || !proof.quorumnet_port || !proof.public_ip) {
|
if (!proof.pubkey_x25519 || !proof.proof->qnet_port || !proof.proof->public_ip) {
|
||||||
MTRACE("Not including node " << pubkey << ": missing x25519(" << to_hex(get_data_as_string(proof.pubkey_x25519)) << "), "
|
MTRACE("Not including node " << pubkey << ": missing x25519(" << to_hex(get_data_as_string(proof.pubkey_x25519)) << "), "
|
||||||
"public_ip(" << epee::string_tools::get_ip_string_from_int32(proof.public_ip) << "), or qnet port(" << proof.quorumnet_port << ")");
|
"public_ip(" << epee::string_tools::get_ip_string_from_int32(proof.proof->public_ip) << "), or qnet port(" << proof.proof->qnet_port << ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
remotes.emplace_back(get_data_as_string(proof.pubkey_x25519),
|
remotes.emplace_back(get_data_as_string(proof.pubkey_x25519),
|
||||||
"tcp://" + epee::string_tools::get_ip_string_from_int32(proof.public_ip) + ":" + std::to_string(proof.quorumnet_port),
|
"tcp://" + epee::string_tools::get_ip_string_from_int32(proof.proof->public_ip) + ":" + std::to_string(proof.proof->qnet_port),
|
||||||
proof.version);
|
proof.proof->version);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Select 4 random SNs to send the data to, but prefer SNs with newer versions because they may have network fixes.
|
// Select 4 random SNs to send the data to, but prefer SNs with newer versions because they may have network fixes.
|
||||||
|
@ -294,9 +295,9 @@ public:
|
||||||
// Lookup the x25519 and ZMQ connection string for all peers
|
// Lookup the x25519 and ZMQ connection string for all peers
|
||||||
qnet.core.get_service_node_list().for_each_service_node_info_and_proof(need_remotes.begin(), need_remotes.end(),
|
qnet.core.get_service_node_list().for_each_service_node_info_and_proof(need_remotes.begin(), need_remotes.end(),
|
||||||
[this](const auto &pubkey, const auto &info, const auto &proof) {
|
[this](const auto &pubkey, const auto &info, const auto &proof) {
|
||||||
if (info.is_active() && proof.pubkey_x25519 && proof.quorumnet_port && proof.public_ip)
|
if (info.is_active() && proof.pubkey_x25519 && proof.proof->qnet_port && proof.proof->public_ip)
|
||||||
remotes.emplace(pubkey, std::make_pair(proof.pubkey_x25519,
|
remotes.emplace(pubkey, std::make_pair(proof.pubkey_x25519,
|
||||||
"tcp://" + epee::string_tools::get_ip_string_from_int32(proof.public_ip) + ":" + std::to_string(proof.quorumnet_port)));
|
"tcp://" + epee::string_tools::get_ip_string_from_int32(proof.proof->public_ip) + ":" + std::to_string(proof.proof->qnet_port)));
|
||||||
});
|
});
|
||||||
|
|
||||||
compute_validator_peers(qbegin, qend, opportunistic);
|
compute_validator_peers(qbegin, qend, opportunistic);
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "rpc/http_server.h"
|
#include "rpc/http_server.h"
|
||||||
#include "rpc/lmq_server.h"
|
#include "rpc/lmq_server.h"
|
||||||
#include "cryptonote_protocol/quorumnet.h"
|
#include "cryptonote_protocol/quorumnet.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
#include "common/password.h"
|
#include "common/password.h"
|
||||||
#include "common/signal_handler.h"
|
#include "common/signal_handler.h"
|
||||||
|
|
|
@ -1678,6 +1678,12 @@ static void append_printable_service_node_list_entry(cryptonote::network_type ne
|
||||||
stream << "Last checked: " << get_human_time_ago(entry.storage_server_reachable_timestamp, now);
|
stream << "Last checked: " << get_human_time_ago(entry.storage_server_reachable_timestamp, now);
|
||||||
stream << ")\n";
|
stream << ")\n";
|
||||||
|
|
||||||
|
//
|
||||||
|
// NOTE: Component Versions
|
||||||
|
//
|
||||||
|
stream << indent2 << "Storage Server Version: " << tools::join(".", entry.storage_server_version) << "\n";
|
||||||
|
stream << indent2 << "Lokinet Router Version: " << tools::join(".", entry.lokinet_version) << "\n";
|
||||||
|
|
||||||
//
|
//
|
||||||
// NOTE: Node Credits
|
// NOTE: Node Credits
|
||||||
//
|
//
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "cryptonote_basic/account.h"
|
#include "cryptonote_basic/account.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||||
#include "cryptonote_core/tx_sanity_check.h"
|
#include "cryptonote_core/tx_sanity_check.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "epee/misc_language.h"
|
#include "epee/misc_language.h"
|
||||||
#include "net/parse.h"
|
#include "net/parse.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
@ -3038,17 +3039,19 @@ namespace cryptonote { namespace rpc {
|
||||||
entry.decommission_count = info.decommission_count;
|
entry.decommission_count = info.decommission_count;
|
||||||
|
|
||||||
m_core.get_service_node_list().access_proof(sn_info.pubkey, [&entry](const auto &proof) {
|
m_core.get_service_node_list().access_proof(sn_info.pubkey, [&entry](const auto &proof) {
|
||||||
entry.service_node_version = proof.version;
|
entry.service_node_version = proof.proof->version;
|
||||||
entry.public_ip = epee::string_tools::get_ip_string_from_int32(proof.public_ip);
|
entry.lokinet_version = proof.proof->lokinet_version;
|
||||||
entry.storage_port = proof.storage_port;
|
entry.storage_server_version = proof.proof->storage_server_version;
|
||||||
entry.storage_lmq_port = proof.storage_lmq_port;
|
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_server_reachable = proof.storage_server_reachable;
|
entry.storage_server_reachable = proof.storage_server_reachable;
|
||||||
entry.pubkey_ed25519 = proof.pubkey_ed25519 ? tools::type_to_hex(proof.pubkey_ed25519) : "";
|
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) : "";
|
entry.pubkey_x25519 = proof.pubkey_x25519 ? tools::type_to_hex(proof.pubkey_x25519) : "";
|
||||||
entry.quorumnet_port = proof.quorumnet_port;
|
entry.quorumnet_port = proof.proof->qnet_port;
|
||||||
|
|
||||||
// NOTE: Service Node Testing
|
// NOTE: Service Node Testing
|
||||||
entry.last_uptime_proof = proof.timestamp;
|
entry.last_uptime_proof = proof.proof->timestamp;
|
||||||
entry.storage_server_reachable = proof.storage_server_reachable;
|
entry.storage_server_reachable = proof.storage_server_reachable;
|
||||||
entry.storage_server_reachable_timestamp = proof.storage_server_reachable_timestamp;
|
entry.storage_server_reachable_timestamp = proof.storage_server_reachable_timestamp;
|
||||||
|
|
||||||
|
@ -3267,7 +3270,7 @@ namespace cryptonote { namespace rpc {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct version_printer { const std::array<int, 3> &v; };
|
struct version_printer { const std::array<uint16_t, 3> &v; };
|
||||||
std::ostream &operator<<(std::ostream &o, const version_printer &vp) { return o << vp.v[0] << '.' << vp.v[1] << '.' << vp.v[2]; }
|
std::ostream &operator<<(std::ostream &o, const version_printer &vp) { return o << vp.v[0] << '.' << vp.v[1] << '.' << vp.v[2]; }
|
||||||
|
|
||||||
// Handles a ping. Returns true if the ping was significant (i.e. first ping after startup, or
|
// Handles a ping. Returns true if the ping was significant (i.e. first ping after startup, or
|
||||||
|
@ -3275,7 +3278,7 @@ namespace cryptonote { namespace rpc {
|
||||||
// argument: true if this ping should trigger an immediate proof send (i.e. first ping after
|
// argument: true if this ping should trigger an immediate proof send (i.e. first ping after
|
||||||
// startup or after a ping expiry), false for an ordinary ping.
|
// startup or after a ping expiry), false for an ordinary ping.
|
||||||
template <typename RPC, typename Success>
|
template <typename RPC, typename Success>
|
||||||
auto handle_ping(std::array<int, 3> cur_version, std::array<int, 3> required, const char* name, std::atomic<std::time_t>& update, time_t lifetime, Success success)
|
auto handle_ping(std::array<uint16_t, 3> cur_version, std::array<uint16_t, 3> required, const char* name, std::atomic<std::time_t>& update, time_t lifetime, Success success)
|
||||||
{
|
{
|
||||||
typename RPC::response res{};
|
typename RPC::response res{};
|
||||||
if (cur_version < required) {
|
if (cur_version < required) {
|
||||||
|
@ -3301,6 +3304,7 @@ namespace cryptonote { namespace rpc {
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
STORAGE_SERVER_PING::response core_rpc_server::invoke(STORAGE_SERVER_PING::request&& req, rpc_context context)
|
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};
|
||||||
return handle_ping<STORAGE_SERVER_PING>(
|
return handle_ping<STORAGE_SERVER_PING>(
|
||||||
{req.version_major, req.version_minor, req.version_patch}, service_nodes::MIN_STORAGE_SERVER_VERSION,
|
{req.version_major, req.version_minor, req.version_patch}, service_nodes::MIN_STORAGE_SERVER_VERSION,
|
||||||
"Storage Server", m_core.m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME,
|
"Storage Server", m_core.m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME,
|
||||||
|
@ -3313,6 +3317,7 @@ namespace cryptonote { namespace rpc {
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
LOKINET_PING::response core_rpc_server::invoke(LOKINET_PING::request&& req, rpc_context context)
|
LOKINET_PING::response core_rpc_server::invoke(LOKINET_PING::request&& req, rpc_context context)
|
||||||
{
|
{
|
||||||
|
m_core.lokinet_version = req.version;
|
||||||
return handle_ping<LOKINET_PING>(
|
return handle_ping<LOKINET_PING>(
|
||||||
req.version, service_nodes::MIN_LOKINET_VERSION,
|
req.version, service_nodes::MIN_LOKINET_VERSION,
|
||||||
"Lokinet", m_core.m_last_lokinet_ping, LOKINET_PING_LIFETIME,
|
"Lokinet", m_core.m_last_lokinet_ping, LOKINET_PING_LIFETIME,
|
||||||
|
|
|
@ -2052,6 +2052,8 @@ namespace rpc {
|
||||||
bool earned_downtime_blocks;
|
bool earned_downtime_blocks;
|
||||||
|
|
||||||
bool service_node_version;
|
bool service_node_version;
|
||||||
|
bool lokinet_version;
|
||||||
|
bool storage_server_version;
|
||||||
bool contributors;
|
bool contributors;
|
||||||
bool total_contributed;
|
bool total_contributed;
|
||||||
bool total_reserved;
|
bool total_reserved;
|
||||||
|
@ -2108,6 +2110,8 @@ namespace rpc {
|
||||||
uint32_t decommission_count; // The number of times the Service Node has been decommissioned since registration
|
uint32_t decommission_count; // The number of times the Service Node has been decommissioned since registration
|
||||||
int64_t earned_downtime_blocks; // The number of blocks earned towards decommissioning, or the number of blocks remaining until deregistration if currently decommissioned
|
int64_t earned_downtime_blocks; // The number of blocks earned towards decommissioning, or the number of blocks remaining until deregistration if currently decommissioned
|
||||||
std::array<uint16_t, 3> service_node_version; // The major, minor, patch version of the Service Node respectively.
|
std::array<uint16_t, 3> service_node_version; // The major, minor, patch version of the Service Node respectively.
|
||||||
|
std::array<uint16_t, 3> lokinet_version; // The major, minor, patch version of the Service Node's lokinet router.
|
||||||
|
std::array<uint16_t, 3> storage_server_version; // The major, minor, patch version of the Service Node's storage server.
|
||||||
std::vector<service_node_contributor> contributors; // Array of contributors, contributing to this Service Node.
|
std::vector<service_node_contributor> contributors; // Array of contributors, contributing to this Service Node.
|
||||||
uint64_t total_contributed; // The total amount of Loki in atomic units contributed to this Service Node.
|
uint64_t total_contributed; // The total amount of Loki in atomic units contributed to this Service Node.
|
||||||
uint64_t total_reserved; // The total amount of Loki in atomic units reserved in this Service Node.
|
uint64_t total_reserved; // The total amount of Loki in atomic units reserved in this Service Node.
|
||||||
|
@ -2183,9 +2187,9 @@ namespace rpc {
|
||||||
|
|
||||||
struct request
|
struct request
|
||||||
{
|
{
|
||||||
int version_major; // Storage Server Major version
|
uint16_t version_major; // Storage Server Major version
|
||||||
int version_minor; // Storage Server Minor version
|
uint16_t version_minor; // Storage Server Minor version
|
||||||
int version_patch; // Storage Server Patch version
|
uint16_t version_patch; // Storage Server Patch version
|
||||||
uint16_t storage_lmq_port; // Storage Server lmq port to include in uptime proofs
|
uint16_t storage_lmq_port; // Storage Server lmq port to include in uptime proofs
|
||||||
KV_MAP_SERIALIZABLE
|
KV_MAP_SERIALIZABLE
|
||||||
};
|
};
|
||||||
|
@ -2200,7 +2204,7 @@ namespace rpc {
|
||||||
|
|
||||||
struct request
|
struct request
|
||||||
{
|
{
|
||||||
std::array<int, 3> version; // Lokinet version
|
std::array<uint16_t, 3> version; // Lokinet version
|
||||||
KV_MAP_SERIALIZABLE
|
KV_MAP_SERIALIZABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "cryptonote_core/blockchain.h"
|
#include "cryptonote_core/blockchain.h"
|
||||||
#include "cryptonote_core/tx_pool.h"
|
#include "cryptonote_core/tx_pool.h"
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "blockchain_utilities/blockchain_objects.h"
|
#include "blockchain_utilities/blockchain_objects.h"
|
||||||
#include "blockchain_db/testdb.h"
|
#include "blockchain_db/testdb.h"
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,12 @@ bool tests::proxy_core::handle_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROO
|
||||||
return false; // never relay these for tests.
|
return false; // never relay these for tests.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tests::proxy_core::handle_btencoded_uptime_proof(const cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation)
|
||||||
|
{
|
||||||
|
// TODO: add tests for core uptime proof checking.
|
||||||
|
return false; // never relay these for tests.
|
||||||
|
}
|
||||||
|
|
||||||
bool tests::proxy_core::get_short_chain_history(std::list<crypto::hash>& ids) {
|
bool tests::proxy_core::get_short_chain_history(std::list<crypto::hash>& ids) {
|
||||||
build_short_history(ids, m_lastblk);
|
build_short_history(ids, m_lastblk);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -85,6 +85,7 @@ namespace tests
|
||||||
int add_blinks(const std::vector<std::shared_ptr<cryptonote::blink_tx>> &blinks) { return 0; }
|
int add_blinks(const std::vector<std::shared_ptr<cryptonote::blink_tx>> &blinks) { return 0; }
|
||||||
bool handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block, cryptonote::block_verification_context& bvc, cryptonote::checkpoint_t *checkpoint, bool update_miner_blocktemplate = true);
|
bool handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block, cryptonote::block_verification_context& bvc, cryptonote::checkpoint_t *checkpoint, bool update_miner_blocktemplate = true);
|
||||||
bool handle_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation);
|
bool handle_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation);
|
||||||
|
bool handle_btencoded_uptime_proof(const cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation);
|
||||||
void pause_mine(){}
|
void pause_mine(){}
|
||||||
void resume_mine(){}
|
void resume_mine(){}
|
||||||
bool on_idle(){return true;}
|
bool on_idle(){return true;}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "block_validation.h"
|
#include "block_validation.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "bulletproofs.h"
|
#include "bulletproofs.h"
|
||||||
#include "device/device.hpp"
|
#include "device/device.hpp"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "chain_split_1.h"
|
#include "chain_split_1.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "chain_switch_1.h"
|
#include "chain_switch_1.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
#include "cryptonote_basic/miner.h"
|
#include "cryptonote_basic/miner.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "oxen_economy.h"
|
#include "oxen_economy.h"
|
||||||
#include "ringct/rctSigs.h"
|
#include "ringct/rctSigs.h"
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "chaingen_tests_list.h"
|
#include "chaingen_tests_list.h"
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "chaingen_tests_list.h"
|
#include "chaingen_tests_list.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/command_line.h"
|
#include "common/command_line.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "transaction_tests.h"
|
#include "transaction_tests.h"
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "double_spend.h"
|
#include "double_spend.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "integer_overflow.h"
|
#include "integer_overflow.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "ringct/rctSigs.h"
|
#include "ringct/rctSigs.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "multisig/multisig.h"
|
#include "multisig/multisig.h"
|
||||||
#include "common/apply_permutation.h"
|
#include "common/apply_permutation.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
#include "cryptonote_core/oxen_name_system.h"
|
#include "cryptonote_core/oxen_name_system.h"
|
||||||
#include "cryptonote_core/service_node_list.h"
|
#include "cryptonote_core/service_node_list.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "oxen_economy.h"
|
#include "oxen_economy.h"
|
||||||
#include "common/random.h"
|
#include "common/random.h"
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "rct.h"
|
#include "rct.h"
|
||||||
#include "device/device.hpp"
|
#include "device/device.hpp"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "ring_signature_1.h"
|
#include "ring_signature_1.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "tx_validation.h"
|
#include "tx_validation.h"
|
||||||
#include "device/device.hpp"
|
#include "device/device.hpp"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "chaingen.h"
|
#include "chaingen.h"
|
||||||
#include "v2_tests.h"
|
#include "v2_tests.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "wallet_tools.h"
|
#include "wallet_tools.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "checkpoints/checkpoints.cpp"
|
#include "checkpoints/checkpoints.cpp"
|
||||||
#include "blockchain_db/testdb.h"
|
#include "blockchain_db/testdb.h"
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
#include "cryptonote_basic/hardfork.h"
|
#include "cryptonote_basic/hardfork.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "blockchain_db/testdb.h"
|
#include "blockchain_db/testdb.h"
|
||||||
#include "checkpoints/checkpoints.h"
|
#include "checkpoints/checkpoints.h"
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "cryptonote_core/blockchain.h"
|
#include "cryptonote_core/blockchain.h"
|
||||||
#include "cryptonote_core/tx_pool.h"
|
#include "cryptonote_core/tx_pool.h"
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "blockchain_utilities/blockchain_objects.h"
|
#include "blockchain_utilities/blockchain_objects.h"
|
||||||
#include "blockchain_db/testdb.h"
|
#include "blockchain_db/testdb.h"
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
int add_blinks(const std::vector<std::shared_ptr<cryptonote::blink_tx>> &blinks) { return 0; }
|
int add_blinks(const std::vector<std::shared_ptr<cryptonote::blink_tx>> &blinks) { return 0; }
|
||||||
bool handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block, cryptonote::block_verification_context& bvc, cryptonote::checkpoint_t const *checkpoint, bool update_miner_blocktemplate = true) { return true; }
|
bool handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block, cryptonote::block_verification_context& bvc, cryptonote::checkpoint_t const *checkpoint, bool update_miner_blocktemplate = true) { return true; }
|
||||||
bool handle_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation) { return false; }
|
bool handle_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation) { return false; }
|
||||||
|
bool handle_btencoded_uptime_proof(const cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation) { return false; }
|
||||||
void pause_mine(){}
|
void pause_mine(){}
|
||||||
void resume_mine(){}
|
void resume_mine(){}
|
||||||
bool on_idle(){return true;}
|
bool on_idle(){return true;}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "cryptonote_core/tx_pool.h"
|
#include "cryptonote_core/tx_pool.h"
|
||||||
#include "cryptonote_core/blockchain.h"
|
#include "cryptonote_core/blockchain.h"
|
||||||
|
#include "cryptonote_core/uptime_proof.h"
|
||||||
#include "blockchain_db/testdb.h"
|
#include "blockchain_db/testdb.h"
|
||||||
|
|
||||||
#include "blockchain_utilities/blockchain_objects.h"
|
#include "blockchain_utilities/blockchain_objects.h"
|
||||||
|
|
Loading…
Reference in a new issue