2020-12-17 06:52:16 +01:00
|
|
|
#include "uptime_proof.h"
|
2021-09-03 07:15:37 +02:00
|
|
|
#include "service_node_list.h"
|
2020-12-17 06:52:16 +01:00
|
|
|
#include "common/string_util.h"
|
2021-08-27 18:03:35 +02:00
|
|
|
#include "epee/string_tools.h"
|
2020-12-17 06:52:16 +01:00
|
|
|
#include "version.h"
|
2022-09-13 08:57:56 +02:00
|
|
|
#include "logging/oxen_logger.h"
|
2020-12-17 06:52:16 +01:00
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#include <sodium/crypto_sign.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace uptime_proof
|
|
|
|
{
|
|
|
|
|
2022-09-13 08:57:56 +02:00
|
|
|
static auto logcat = oxen::log::Cat("uptime_proof");
|
|
|
|
|
2020-12-17 06:52:16 +01:00
|
|
|
//Constructor for the uptime proof, will take the service node keys as a param and sign
|
2021-04-08 18:42:33 +02:00
|
|
|
Proof::Proof(
|
|
|
|
uint32_t sn_public_ip,
|
|
|
|
uint16_t sn_storage_https_port,
|
|
|
|
uint16_t sn_storage_omq_port,
|
|
|
|
const std::array<uint16_t, 3> ss_version,
|
|
|
|
uint16_t quorumnet_port,
|
|
|
|
const std::array<uint16_t, 3> lokinet_version,
|
|
|
|
const service_nodes::service_node_keys& keys) :
|
|
|
|
version{OXEN_VERSION},
|
|
|
|
pubkey{keys.pub},
|
|
|
|
timestamp{static_cast<uint64_t>(time(nullptr))},
|
|
|
|
public_ip{sn_public_ip},
|
|
|
|
pubkey_ed25519{keys.pub_ed25519},
|
|
|
|
qnet_port{quorumnet_port},
|
|
|
|
storage_https_port{sn_storage_https_port},
|
|
|
|
storage_omq_port{sn_storage_omq_port},
|
2021-06-18 01:47:00 +02:00
|
|
|
storage_server_version{ss_version},
|
|
|
|
lokinet_version{lokinet_version}
|
2020-12-17 06:52:16 +01:00
|
|
|
{
|
2021-06-18 01:47:00 +02:00
|
|
|
crypto::hash hash = hash_uptime_proof();
|
2020-12-17 06:52:16 +01:00
|
|
|
|
|
|
|
crypto::generate_signature(hash, keys.pub, keys.key, sig);
|
Overhaul and fix crypto::{public_key,ec_point,etc.} types
- Remove implicit `operator bool` from ec_point/public_key/etc. which
was causing all sorts of implicit conversion mess and bugs.
- Change ec_point/public_key/etc. to use a `std::array<unsigned char,
32>` (via a base type) rather than a C-array of char that has to be
reinterpret_cast<>'ed all over the place.
- Add methods to ec_point/public_key/etc. that make it work more like a
container of bytes (`.data()`, `.size()`, `operator[]`, `begin()`,
`end()`).
- Make a generic `crypto::null<T>` that is a constexpr all-0 `T`, rather
than the mishmash `crypto::null_hash`, crypto::null_pkey,
crypto::hash::null(), and so on.
- Replace three metric tons of `crypto::hash blahblah =
crypto::null_hash;` with the much simpler `crypto::hash blahblah{};`,
because there's no need to make a copy of a null hash in all these
cases. (Likewise for a few other null_whatevers).
- Remove a whole bunch of `if (blahblah == crypto::null_hash)` and `if
(blahblah != crypto::null_hash)` with the more concise `if
(!blahblah)` and `if (blahblah)` (which are fine via the newly
*explicit* bool conversion operators).
- `crypto::signature` becomes a 64-byte container (as above) but with
`c()` and `r()` to get the c() and r() data pointers. (Previously
`.c` and `.r` were `ec_scalar`s).
- Delete with great prejudice CRYPTO_MAKE_COMPARABLE and
CRYPTO_MAKE_HASHABLE and all the other utter trash in
`crypto/generic-ops.h`.
- De-inline functions in very common crypto/*.h files so that they don't
have to get compiled 300 times.
- Remove the disgusting include-a-C-header-inside-a-C++-namespace
garbage from some crypto headers trying to be both a C and *different*
C++ header at once.
- Remove the toxic, disgusting, shameful `operator&` on ec_scalar, etc.
that replace `&x` with `reinterpret_cast x into an unsigned char*`.
This was pure toxic waste.
- changed some `<<` outputs to fmt
- Random other small changes encountered while fixing everything that
cascaded out of the above changes.
2022-10-15 03:22:44 +02:00
|
|
|
crypto_sign_detached(sig_ed25519.data(), nullptr, hash.data(), hash.size(), keys.key_ed25519.data());
|
2020-12-17 06:52:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//Deserialize from a btencoded string into our Proof instance
|
|
|
|
Proof::Proof(const std::string& serialized_proof)
|
|
|
|
{
|
|
|
|
try {
|
2022-02-10 19:25:55 +01:00
|
|
|
using namespace oxenc;
|
2021-03-02 04:57:23 +01:00
|
|
|
|
|
|
|
const bt_dict bt_proof = bt_deserialize<bt_dict>(serialized_proof);
|
2020-12-17 06:52:16 +01:00
|
|
|
//snode_version <X,X,X>
|
2021-03-02 04:57:23 +01:00
|
|
|
const bt_list& bt_version = var::get<bt_list>(bt_proof.at("v"));
|
2020-12-17 06:52:16 +01:00
|
|
|
int k = 0;
|
2021-03-02 04:57:23 +01:00
|
|
|
for (bt_value const &i: bt_version){
|
|
|
|
version[k++] = static_cast<uint16_t>(get_int<unsigned>(i));
|
2020-12-17 06:52:16 +01:00
|
|
|
}
|
|
|
|
//timestamp
|
2021-03-02 04:57:23 +01:00
|
|
|
timestamp = get_int<unsigned>(bt_proof.at("t"));
|
2020-12-17 06:52:16 +01:00
|
|
|
//public_ip
|
2021-01-28 01:07:57 +01:00
|
|
|
bool succeeded = epee::string_tools::get_ip_int32_from_string(public_ip, var::get<std::string>(bt_proof.at("ip")));
|
2020-12-17 06:52:16 +01:00
|
|
|
//storage_port
|
2021-04-08 18:42:33 +02:00
|
|
|
storage_https_port = static_cast<uint16_t>(get_int<unsigned>(bt_proof.at("shp")));
|
2020-12-17 06:52:16 +01:00
|
|
|
//pubkey_ed25519
|
2021-01-28 01:07:57 +01:00
|
|
|
pubkey_ed25519 = tools::make_from_guts<crypto::ed25519_public_key>(var::get<std::string>(bt_proof.at("pke")));
|
2020-12-17 06:52:16 +01:00
|
|
|
//pubkey
|
2021-01-28 01:07:57 +01:00
|
|
|
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")));
|
2020-12-17 06:52:16 +01:00
|
|
|
else
|
Overhaul and fix crypto::{public_key,ec_point,etc.} types
- Remove implicit `operator bool` from ec_point/public_key/etc. which
was causing all sorts of implicit conversion mess and bugs.
- Change ec_point/public_key/etc. to use a `std::array<unsigned char,
32>` (via a base type) rather than a C-array of char that has to be
reinterpret_cast<>'ed all over the place.
- Add methods to ec_point/public_key/etc. that make it work more like a
container of bytes (`.data()`, `.size()`, `operator[]`, `begin()`,
`end()`).
- Make a generic `crypto::null<T>` that is a constexpr all-0 `T`, rather
than the mishmash `crypto::null_hash`, crypto::null_pkey,
crypto::hash::null(), and so on.
- Replace three metric tons of `crypto::hash blahblah =
crypto::null_hash;` with the much simpler `crypto::hash blahblah{};`,
because there's no need to make a copy of a null hash in all these
cases. (Likewise for a few other null_whatevers).
- Remove a whole bunch of `if (blahblah == crypto::null_hash)` and `if
(blahblah != crypto::null_hash)` with the more concise `if
(!blahblah)` and `if (blahblah)` (which are fine via the newly
*explicit* bool conversion operators).
- `crypto::signature` becomes a 64-byte container (as above) but with
`c()` and `r()` to get the c() and r() data pointers. (Previously
`.c` and `.r` were `ec_scalar`s).
- Delete with great prejudice CRYPTO_MAKE_COMPARABLE and
CRYPTO_MAKE_HASHABLE and all the other utter trash in
`crypto/generic-ops.h`.
- De-inline functions in very common crypto/*.h files so that they don't
have to get compiled 300 times.
- Remove the disgusting include-a-C-header-inside-a-C++-namespace
garbage from some crypto headers trying to be both a C and *different*
C++ header at once.
- Remove the toxic, disgusting, shameful `operator&` on ec_scalar, etc.
that replace `&x` with `reinterpret_cast x into an unsigned char*`.
This was pure toxic waste.
- changed some `<<` outputs to fmt
- Random other small changes encountered while fixing everything that
cascaded out of the above changes.
2022-10-15 03:22:44 +02:00
|
|
|
std::memcpy(pubkey.data(), pubkey_ed25519.data(), 32);
|
2020-12-17 06:52:16 +01:00
|
|
|
//qnet_port
|
2021-03-02 04:57:23 +01:00
|
|
|
qnet_port = get_int<unsigned>(bt_proof.at("q"));
|
2021-04-08 18:42:33 +02:00
|
|
|
//storage_omq_port
|
|
|
|
storage_omq_port = get_int<unsigned>(bt_proof.at("sop"));
|
2020-12-17 06:52:16 +01:00
|
|
|
//storage_version
|
2021-03-02 04:57:23 +01:00
|
|
|
const bt_list& bt_storage_version = var::get<bt_list>(bt_proof.at("sv"));
|
2020-12-17 06:52:16 +01:00
|
|
|
k = 0;
|
2021-03-02 04:57:23 +01:00
|
|
|
for (bt_value const &i: bt_storage_version){
|
|
|
|
storage_server_version[k++] = static_cast<uint16_t>(get_int<unsigned>(i));
|
2020-12-17 06:52:16 +01:00
|
|
|
}
|
|
|
|
//lokinet_version
|
2021-03-02 04:57:23 +01:00
|
|
|
const bt_list& bt_lokinet_version = var::get<bt_list>(bt_proof.at("lv"));
|
2020-12-17 06:52:16 +01:00
|
|
|
k = 0;
|
2021-03-02 04:57:23 +01:00
|
|
|
for (bt_value const &i: bt_lokinet_version){
|
|
|
|
lokinet_version[k++] = static_cast<uint16_t>(get_int<unsigned>(i));
|
2020-12-17 06:52:16 +01:00
|
|
|
}
|
|
|
|
} catch (const std::exception& e) {
|
2022-09-13 08:57:56 +02:00
|
|
|
oxen::log::warning(logcat, "deserialization failed: {}", e.what());
|
2020-12-17 06:52:16 +01:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-28 01:07:57 +01:00
|
|
|
|
2020-12-17 06:52:16 +01:00
|
|
|
crypto::hash Proof::hash_uptime_proof() const
|
|
|
|
{
|
|
|
|
crypto::hash result;
|
|
|
|
|
2021-03-02 04:57:23 +01:00
|
|
|
std::string serialized_proof = bt_serialize(bt_encode_uptime_proof());
|
2020-12-17 06:52:16 +01:00
|
|
|
size_t buf_size = serialized_proof.size();
|
|
|
|
crypto::cn_fast_hash(serialized_proof.data(), buf_size, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-02-10 19:25:55 +01:00
|
|
|
oxenc::bt_dict Proof::bt_encode_uptime_proof() const
|
2020-12-17 06:52:16 +01:00
|
|
|
{
|
2022-02-10 19:25:55 +01:00
|
|
|
oxenc::bt_dict encoded_proof{
|
2021-01-28 01:07:57 +01:00
|
|
|
//version
|
2022-02-10 19:25:55 +01:00
|
|
|
{"v", oxenc::bt_list{{version[0], version[1], version[2]}}},
|
2021-01-28 01:07:57 +01:00
|
|
|
//timestamp
|
|
|
|
{"t", timestamp},
|
|
|
|
//public_ip
|
|
|
|
{"ip", epee::string_tools::get_ip_string_from_int32(public_ip)},
|
|
|
|
//storage_port
|
2021-04-08 18:42:33 +02:00
|
|
|
{"shp", storage_https_port},
|
2021-01-28 01:07:57 +01:00
|
|
|
//pubkey_ed25519
|
|
|
|
{"pke", tools::view_guts(pubkey_ed25519)},
|
|
|
|
//qnet_port
|
|
|
|
{"q", qnet_port},
|
2021-04-08 18:42:33 +02:00
|
|
|
//storage_omq_port
|
|
|
|
{"sop", storage_omq_port},
|
2021-01-28 01:07:57 +01:00
|
|
|
//storage_version
|
2022-02-10 19:25:55 +01:00
|
|
|
{"sv", oxenc::bt_list{{storage_server_version[0], storage_server_version[1], storage_server_version[2]}}},
|
2021-01-28 01:07:57 +01:00
|
|
|
//lokinet_version
|
2022-02-10 19:25:55 +01:00
|
|
|
{"lv", oxenc::bt_list{{lokinet_version[0], lokinet_version[1], lokinet_version[2]}}},
|
2020-12-17 06:52:16 +01:00
|
|
|
};
|
|
|
|
|
2021-04-30 02:23:16 +02:00
|
|
|
if (tools::view_guts(pubkey) != tools::view_guts(pubkey_ed25519)) {
|
|
|
|
encoded_proof["pk"] = tools::view_guts(pubkey);
|
|
|
|
}
|
2020-12-17 06:52:16 +01:00
|
|
|
|
|
|
|
return encoded_proof;
|
|
|
|
}
|
|
|
|
|
|
|
|
cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request Proof::generate_request() const
|
|
|
|
{
|
|
|
|
cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request request;
|
2021-03-02 04:57:23 +01:00
|
|
|
request.proof = bt_serialize(this->bt_encode_uptime_proof());
|
2020-12-17 06:52:16 +01:00
|
|
|
request.sig = tools::view_guts(this->sig);
|
|
|
|
request.ed_sig = tools::view_guts(this->sig_ed25519);
|
|
|
|
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
2021-09-03 07:17:07 +02:00
|
|
|
bool operator==(const Proof& lhs, const Proof& rhs)
|
2021-01-28 01:07:57 +01:00
|
|
|
{
|
|
|
|
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) ||
|
2021-04-08 18:42:33 +02:00
|
|
|
(lhs.storage_https_port != rhs.storage_https_port) ||
|
|
|
|
(lhs.storage_omq_port != rhs.storage_omq_port) ||
|
2021-01-28 01:07:57 +01:00
|
|
|
(lhs.qnet_port != rhs.qnet_port) ||
|
2021-04-08 18:42:33 +02:00
|
|
|
(lhs.version != rhs.version) ||
|
|
|
|
(lhs.storage_server_version != rhs.storage_server_version) ||
|
|
|
|
(lhs.lokinet_version != rhs.lokinet_version))
|
2021-01-28 01:07:57 +01:00
|
|
|
result = false;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-09-03 07:17:07 +02:00
|
|
|
bool operator!=(const Proof& lhs, const Proof& rhs)
|
2021-01-28 01:07:57 +01:00
|
|
|
{
|
|
|
|
return !(lhs == rhs);
|
|
|
|
}
|
2020-12-17 06:52:16 +01:00
|
|
|
|
2021-09-03 07:17:07 +02:00
|
|
|
}
|