mirror of https://github.com/oxen-io/oxen-core.git
Code review
- constexpr functions in common/loki.h for inlining - move hex functions out from common/loki.h to common/hex.h - use and apply prev_txid on LNS TX's to all LNS types (for updating in the future) - add lns burn type, for custom burn amounts - accept and validate lokinet addresses via base32z - return lokinet addresses in RPC LNS calls via base32z - updated Messenger references to Session - update documentation to note that only Session LNS entries are allowed currently - remove raw c-string interface from LNS db - update multi-SQL queries into single SQL queries - remove tx estimation backlog in anticipation for 2 priorities only, blink + unimportant
This commit is contained in:
parent
dafc95ac91
commit
e3a6f20f85
|
@ -30,6 +30,7 @@
|
|||
include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
set(common_sources
|
||||
base32z.cpp
|
||||
base58.cpp
|
||||
command_line.cpp
|
||||
dns_utils.cpp
|
||||
|
@ -65,6 +66,7 @@ set(common_headers)
|
|||
|
||||
set(common_private_headers
|
||||
apply_permutation.h
|
||||
base32z.h
|
||||
base58.h
|
||||
boost_serialization_helper.h
|
||||
command_line.h
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include "base32z.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace base32z
|
||||
{
|
||||
static const std::unordered_map<char, uint8_t> zbase32_reverse_alpha = {
|
||||
{'y', 0}, {'b', 1}, {'n', 2}, {'d', 3}, {'r', 4}, {'f', 5}, {'g', 6}, {'8', 7},
|
||||
{'e', 8}, {'j', 9}, {'k', 10}, {'m', 11}, {'c', 12}, {'p', 13}, {'q', 14}, {'x', 15},
|
||||
{'o', 16}, {'t', 17}, {'1', 18}, {'u', 19}, {'w', 20}, {'i', 21}, {'s', 22}, {'z', 23},
|
||||
{'a', 24}, {'3', 25}, {'4', 26}, {'5', 27}, {'h', 28}, {'7', 29}, {'6', 30}, {'9', 31}};
|
||||
|
||||
static size_t decode_size(size_t sz)
|
||||
{
|
||||
auto d = div(sz, 5);
|
||||
if (d.rem) d.quot++;
|
||||
return 8 * d.quot;
|
||||
}
|
||||
|
||||
bool decode(std::string const &src, crypto::ed25519_public_key &dest)
|
||||
{
|
||||
int tmp = 0, bits = 0;
|
||||
size_t idx = 0;
|
||||
const size_t len = decode_size(sizeof(dest));
|
||||
const size_t out_len = sizeof(dest);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
char ch = src[i];
|
||||
if (ch)
|
||||
{
|
||||
auto itr = zbase32_reverse_alpha.find(ch);
|
||||
if (itr == zbase32_reverse_alpha.end()) return false;
|
||||
ch = itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return idx == out_len;
|
||||
}
|
||||
tmp |= ch;
|
||||
bits += 5;
|
||||
if (bits >= 8)
|
||||
{
|
||||
if (idx >= out_len) return false;
|
||||
dest.data[idx] = tmp >> (bits - 8);
|
||||
bits -= 8;
|
||||
idx++;
|
||||
}
|
||||
tmp <<= 5;
|
||||
}
|
||||
return idx == out_len;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
struct ed25519_public_key;
|
||||
};
|
||||
|
||||
namespace base32z
|
||||
{
|
||||
bool decode(std::string const &src, crypto::ed25519_public_key &dest);
|
||||
|
||||
/// adapted from i2pd
|
||||
template <typename stack_t>
|
||||
const char *encode(std::string const &src, stack_t &stack)
|
||||
{
|
||||
// from https://en.wikipedia.org/wiki/Base32#z-base-32
|
||||
static const char zbase32_alpha[] = {'y', 'b', 'n', 'd', 'r', 'f', 'g', '8', 'e', 'j', 'k', 'm', 'c', 'p', 'q', 'x',
|
||||
'o', 't', '1', 'u', 'w', 'i', 's', 'z', 'a', '3', '4', '5', 'h', '7', '6', '9'};
|
||||
|
||||
size_t ret = 0, pos = 1;
|
||||
int bits = 8;
|
||||
uint32_t tmp = src[0];
|
||||
size_t len = sizeof(src);
|
||||
while (ret < sizeof(stack) && (bits > 0 || pos < len))
|
||||
{
|
||||
if (bits < 5)
|
||||
{
|
||||
if (pos < len)
|
||||
{
|
||||
tmp <<= 8;
|
||||
tmp |= src[pos] & 0xFF;
|
||||
pos++;
|
||||
bits += 8;
|
||||
}
|
||||
else // last byte
|
||||
{
|
||||
tmp <<= (5 - bits);
|
||||
bits = 5;
|
||||
}
|
||||
}
|
||||
|
||||
bits -= 5;
|
||||
int ind = (tmp >> bits) & 0x1F;
|
||||
if (ret < sizeof(stack))
|
||||
{
|
||||
stack[ret] = zbase32_alpha[ind];
|
||||
ret++;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
return &stack[0];
|
||||
}
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
namespace hex
|
||||
{
|
||||
constexpr bool char_is_hex(char c)
|
||||
{
|
||||
bool result = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr char from_hex_digit(char x) {
|
||||
return
|
||||
(x >= '0' && x <= '9') ? x - '0' :
|
||||
(x >= 'a' && x <= 'f') ? x - ('a' - 10):
|
||||
(x >= 'A' && x <= 'F') ? x - ('A' - 10):
|
||||
0;
|
||||
}
|
||||
constexpr char from_hex_pair(char a, char b) { return (from_hex_digit(a) << 4) | from_hex_digit(b); }
|
||||
|
||||
// Creates a string from a character sequence of hex digits. Undefined behaviour if any characters
|
||||
// are not in [0-9a-fA-F] or if the input sequence length is not even.
|
||||
template <typename It>
|
||||
std::string from_hex(It begin, It end) {
|
||||
using std::distance;
|
||||
using std::next;
|
||||
assert(distance(begin, end) % 2 == 0);
|
||||
std::string raw;
|
||||
raw.reserve(distance(begin, end) / 2);
|
||||
while (begin != end) {
|
||||
char a = *begin++;
|
||||
char b = *begin++;
|
||||
raw += from_hex_pair(a, b);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
}
|
|
@ -498,17 +498,3 @@ loki::round (double x)
|
|||
return z;
|
||||
}
|
||||
|
||||
uint64_t loki::clamp_u64(uint64_t val, uint64_t min, uint64_t max)
|
||||
{
|
||||
assert(min <= max);
|
||||
if (val < min) val = min;
|
||||
else if (val > max) val = max;
|
||||
return val;
|
||||
}
|
||||
|
||||
bool loki::char_is_hex(char c)
|
||||
{
|
||||
bool result = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,39 +36,20 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#define LOKI_RPC_DOC_INTROSPECT
|
||||
namespace loki
|
||||
{
|
||||
double round (double);
|
||||
double exp2 (double);
|
||||
uint64_t clamp_u64 (uint64_t val, uint64_t min, uint64_t max);
|
||||
bool char_is_hex (char c);
|
||||
|
||||
constexpr char from_hex_digit(char x) {
|
||||
return
|
||||
(x >= '0' && x <= '9') ? x - '0' :
|
||||
(x >= 'a' && x <= 'f') ? x - ('a' - 10):
|
||||
(x >= 'A' && x <= 'F') ? x - ('A' - 10):
|
||||
0;
|
||||
}
|
||||
constexpr char from_hex_pair(char a, char b) { return (from_hex_digit(a) << 4) | from_hex_digit(b); }
|
||||
|
||||
// Creates a string from a character sequence of hex digits. Undefined behaviour if any characters
|
||||
// are not in [0-9a-fA-F] or if the input sequence length is not even.
|
||||
template <typename It>
|
||||
std::string from_hex(It begin, It end) {
|
||||
using std::distance;
|
||||
using std::next;
|
||||
assert(distance(begin, end) % 2 == 0);
|
||||
std::string raw;
|
||||
raw.reserve(distance(begin, end) / 2);
|
||||
while (begin != end) {
|
||||
char a = *begin++;
|
||||
char b = *begin++;
|
||||
raw += from_hex_pair(a, b);
|
||||
}
|
||||
return raw;
|
||||
constexpr uint64_t clamp_u64(uint64_t val, uint64_t min, uint64_t max)
|
||||
{
|
||||
assert(min <= max);
|
||||
if (val < min) val = min;
|
||||
else if (val > max) val = max;
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename lambda_t>
|
||||
|
|
|
@ -62,18 +62,6 @@
|
|||
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
|
||||
#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01
|
||||
|
||||
namespace lns
|
||||
{
|
||||
enum struct mapping_type : uint16_t
|
||||
{
|
||||
messenger = 0,
|
||||
start_reserved = 1,
|
||||
blockchain = 2,
|
||||
lokinet = 3,
|
||||
end_reserved = 64,
|
||||
};
|
||||
}
|
||||
|
||||
namespace service_nodes {
|
||||
enum class new_state : uint16_t
|
||||
{
|
||||
|
@ -401,7 +389,7 @@ namespace cryptonote
|
|||
uint16_t type;
|
||||
std::string name;
|
||||
std::string value; // binary format of the name->value mapping
|
||||
crypto::hash prev_txid = crypto::null_hash; // previous txid that purchased the mapping, only applicable if lokinet
|
||||
crypto::hash prev_txid = crypto::null_hash; // previous txid that purchased the mapping
|
||||
|
||||
tx_extra_loki_name_system() = default;
|
||||
tx_extra_loki_name_system(crypto::ed25519_public_key const &owner, uint16_t type, std::string const &name, std::string const &value, crypto::hash const &prev_txid)
|
||||
|
@ -419,8 +407,7 @@ namespace cryptonote
|
|||
FIELD(type);
|
||||
FIELD(name);
|
||||
FIELD(value);
|
||||
if (type == static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
FIELD(prev_txid);
|
||||
FIELD(prev_txid);
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "checkpoints/checkpoints.h"
|
||||
#include "common/loki.h"
|
||||
#include "common/hex.h"
|
||||
#include "common/base32z.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||
|
@ -32,6 +34,7 @@ enum struct lns_sql_type
|
|||
get_setting,
|
||||
get_mapping,
|
||||
get_mappings_by_user,
|
||||
get_mapping_by_name_and_type,
|
||||
get_mappings_on_height_and_newer,
|
||||
get_sentinel_end,
|
||||
};
|
||||
|
@ -60,6 +63,7 @@ enum struct mapping_record_row
|
|||
prev_txid,
|
||||
register_height,
|
||||
user_id,
|
||||
_count,
|
||||
};
|
||||
|
||||
static bool sql_copy_blob(sqlite3_stmt *statement, int row, void *dest, int dest_size)
|
||||
|
@ -118,6 +122,7 @@ static bool sql_run_statement(cryptonote::network_type nettype, lns_sql_type typ
|
|||
}
|
||||
break;
|
||||
|
||||
case lns_sql_type::get_mapping_by_name_and_type: /* FALLTHRU */
|
||||
case lns_sql_type::get_mappings_on_height_and_newer: /* FALLTHRU */
|
||||
case lns_sql_type::get_mappings_by_user: /* FALLTHRU */
|
||||
case lns_sql_type::get_mapping:
|
||||
|
@ -142,16 +147,27 @@ static bool sql_run_statement(cryptonote::network_type nettype, lns_sql_type typ
|
|||
if (!sql_copy_blob(statement, static_cast<int>(mapping_record_row::prev_txid), tmp_entry.prev_txid.data, sizeof(tmp_entry.prev_txid)))
|
||||
return false;
|
||||
|
||||
|
||||
data_loaded = true;
|
||||
if (type == lns_sql_type::get_mappings_by_user || type == lns_sql_type::get_mappings_on_height_and_newer)
|
||||
|
||||
if (type == lns_sql_type::get_mapping_by_name_and_type)
|
||||
{
|
||||
int constexpr last_column = tools::enum_count<mapping_record_row> + 1;
|
||||
auto *entry = reinterpret_cast<mapping_and_user_record *>(context);
|
||||
if (!sql_copy_blob(statement, last_column, entry->owner.data, sizeof(entry->owner)))
|
||||
return false;
|
||||
|
||||
entry->mapping = std::move(tmp_entry);
|
||||
}
|
||||
else if (type == lns_sql_type::get_mappings_by_user || type == lns_sql_type::get_mappings_on_height_and_newer)
|
||||
{
|
||||
auto *records = reinterpret_cast<std::vector<mapping_record> *>(context);
|
||||
records->emplace_back(std::move(tmp_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping_record *entry = reinterpret_cast<mapping_record *>(context);
|
||||
*entry = std::move(tmp_entry);
|
||||
auto *entry = reinterpret_cast<mapping_record *>(context);
|
||||
*entry = std::move(tmp_entry);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -198,10 +214,32 @@ static bool sql_compile_statement(sqlite3 *db, char const *query, int query_len,
|
|||
return result;
|
||||
}
|
||||
|
||||
uint64_t burn_requirement_in_atomic_loki(uint8_t hf_version)
|
||||
burn_type mapping_type_to_burn_type(mapping_type in)
|
||||
{
|
||||
(void)hf_version;
|
||||
return 30 * COIN;
|
||||
burn_type result = burn_type::custom;
|
||||
switch (in)
|
||||
{
|
||||
case mapping_type::lokinet: result = burn_type::lokinet_1year; break;
|
||||
case mapping_type::session: result = burn_type::session; break;
|
||||
case mapping_type::wallet: result = burn_type::wallet; break;
|
||||
default: break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t burn_requirement_in_atomic_loki(uint8_t /*hf_version*/, burn_type type)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
switch (type)
|
||||
{
|
||||
case burn_type::lokinet_1year: /* FALLTHRU */
|
||||
case burn_type::session: /* FALLTHRU */
|
||||
case burn_type::wallet: /* FALLTHRU */
|
||||
case burn_type::custom: /* FALLTHRU */
|
||||
default: result = 30 * COIN;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
sqlite3 *init_loki_name_system(char const *file_path)
|
||||
|
@ -261,29 +299,28 @@ static bool char_is_alphanum(char c)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool validate_lns_name(uint16_t type, char const *name, int name_len, std::string *reason)
|
||||
bool validate_lns_name(uint16_t type, std::string const &name, std::string *reason)
|
||||
{
|
||||
std::stringstream err_stream;
|
||||
LOKI_DEFER { if (reason) *reason = err_stream.str(); };
|
||||
|
||||
int max_name_len = lns::GENERIC_NAME_MAX;
|
||||
if (type == static_cast<uint16_t>(mapping_type::messenger)) max_name_len = lns::MESSENGER_DISPLAY_NAME_MAX;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::blockchain)) max_name_len = lns::BLOCKCHAIN_NAME_MAX;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::lokinet)) max_name_len = lns::LOKINET_DOMAIN_NAME_MAX;
|
||||
size_t max_name_len = lns::GENERIC_NAME_MAX;
|
||||
if (type == static_cast<uint16_t>(mapping_type::session)) max_name_len = lns::SESSION_DISPLAY_NAME_MAX;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::wallet)) max_name_len = lns::WALLET_NAME_MAX;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::lokinet)) max_name_len = lns::LOKINET_DOMAIN_NAME_MAX;
|
||||
|
||||
// NOTE: Validate name length
|
||||
if (name_len > max_name_len || name_len == 0)
|
||||
if (name.empty() || name.size() > max_name_len)
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the name's length=" << name_len << " is 0 or exceeds the maximum length=" << max_name_len << ", given name=";
|
||||
err_stream.write(name, name_len);
|
||||
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the name's length=" << name.size() << " is 0 or exceeds the maximum length=" << max_name_len << ", given name=" << name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: Validate domain specific requirements
|
||||
if (type == static_cast<uint16_t>(mapping_type::messenger))
|
||||
if (type == static_cast<uint16_t>(mapping_type::session))
|
||||
{
|
||||
}
|
||||
else if (type == static_cast<uint16_t>(mapping_type::lokinet))
|
||||
|
@ -292,12 +329,11 @@ bool validate_lns_name(uint16_t type, char const *name, int name_len, std::strin
|
|||
// ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.loki$
|
||||
{
|
||||
char const SHORTEST_DOMAIN[] = "a.loki";
|
||||
if (name_len < static_cast<int>(loki::char_count(SHORTEST_DOMAIN)))
|
||||
if (name.size() < static_cast<int>(loki::char_count(SHORTEST_DOMAIN)))
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the name is shorter than the shortest possible name=" << SHORTEST_DOMAIN << ", given name=";
|
||||
err_stream.write(name, name_len);
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the name is shorter than the shortest possible name=" << SHORTEST_DOMAIN << ", given name=" << name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -307,20 +343,18 @@ bool validate_lns_name(uint16_t type, char const *name, int name_len, std::strin
|
|||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the name does not start with an alphanumeric character, name=";
|
||||
err_stream.write(name, name_len);
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the name does not start with an alphanumeric character, name=" << name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char const SUFFIX[] = ".loki";
|
||||
char const *name_suffix = name + (name_len - loki::char_count(SUFFIX));
|
||||
char const *name_suffix = name.data() + (name.size() - loki::char_count(SUFFIX));
|
||||
if (memcmp(name_suffix, SUFFIX, loki::char_count(SUFFIX)) != 0) // Must end with .loki
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the name does not end with the domain .loki, name=";
|
||||
err_stream.write(name, name_len);
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the name does not end with the domain .loki, name=" << name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -330,13 +364,12 @@ bool validate_lns_name(uint16_t type, char const *name, int name_len, std::strin
|
|||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the character preceeding the <char>.loki is not alphanumeric, char=" << char_preceeding_suffix[0] << ", name=";
|
||||
err_stream.write(name, name_len);
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the character preceeding the <char>.loki is not alphanumeric, char=" << char_preceeding_suffix[0] << ", name=" << name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char const *begin = name + 1;
|
||||
char const *begin = name.data() + 1;
|
||||
char const *end = char_preceeding_suffix;
|
||||
for (char const *it = begin; it < end; it++) // Inbetween start and preceeding suffix, alphanumeric and hyphen characters permitted
|
||||
{
|
||||
|
@ -345,8 +378,7 @@ bool validate_lns_name(uint16_t type, char const *name, int name_len, std::strin
|
|||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the domain name contains more than the permitted alphanumeric or hyphen characters name=";
|
||||
err_stream.write(name, name_len);
|
||||
err_stream << "LNS type=lokinet, specifies mapping from name -> value where the domain name contains more than the permitted alphanumeric or hyphen characters name=" << name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -356,17 +388,17 @@ bool validate_lns_name(uint16_t type, char const *name, int name_len, std::strin
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool check_lengths(uint16_t type, char const *value, int len, int max, bool require_exact_len, std::string *reason)
|
||||
static bool check_lengths(uint16_t type, std::string const &value, size_t max, bool require_exact_len, std::string *reason)
|
||||
{
|
||||
bool result = true;
|
||||
if (require_exact_len)
|
||||
{
|
||||
if (len != max)
|
||||
if (value.size() != max)
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len > max || len == 0)
|
||||
if (value.size() > max || value.size() == 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
@ -377,11 +409,10 @@ static bool check_lengths(uint16_t type, char const *value, int len, int max, bo
|
|||
if (reason)
|
||||
{
|
||||
std::stringstream err_stream;
|
||||
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the value's length=" << len;
|
||||
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the value's length=" << value.size();
|
||||
if (require_exact_len) err_stream << ", does not equal the required length=";
|
||||
else err_stream <<" is 0 or exceeds the maximum length=";
|
||||
err_stream << max << ", given value=";
|
||||
err_stream.write(value, len);
|
||||
err_stream << max << ", given value=" << value;
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
}
|
||||
|
@ -389,32 +420,30 @@ static bool check_lengths(uint16_t type, char const *value, int len, int max, bo
|
|||
return result;
|
||||
}
|
||||
|
||||
bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, char const *value, int value_len, lns_value *blob, std::string *reason)
|
||||
bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, std::string const &value, lns_value *blob, std::string *reason)
|
||||
{
|
||||
if (blob) *blob = {};
|
||||
std::stringstream err_stream;
|
||||
|
||||
cryptonote::address_parse_info addr_info = {};
|
||||
|
||||
static_assert(GENERIC_VALUE_MAX >= MESSENGER_PUBLIC_KEY_BINARY_LENGTH, "lns_value assumes the largest blob size required, all other values should be able to fit into this buffer");
|
||||
static_assert(GENERIC_VALUE_MAX >= SESSION_PUBLIC_KEY_BINARY_LENGTH, "lns_value assumes the largest blob size required, all other values should be able to fit into this buffer");
|
||||
static_assert(GENERIC_VALUE_MAX >= LOKINET_ADDRESS_BINARY_LENGTH, "lns_value assumes the largest blob size required, all other values should be able to fit into this buffer");
|
||||
static_assert(GENERIC_VALUE_MAX >= sizeof(addr_info.address), "lns_value assumes the largest blob size required, all other values should be able to fit into this buffer");
|
||||
if (type == static_cast<uint16_t>(mapping_type::blockchain))
|
||||
if (type == static_cast<uint16_t>(mapping_type::wallet))
|
||||
{
|
||||
if (value_len == 0 || !get_account_address_from_str(addr_info, nettype, std::string(value, value_len)))
|
||||
if (value.empty() || !get_account_address_from_str(addr_info, nettype, value))
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
if (value_len == 0)
|
||||
if (value.empty())
|
||||
{
|
||||
err_stream << "The value=";
|
||||
err_stream.write(value, value_len);
|
||||
err_stream << "The value=" << value;
|
||||
err_stream << ", mapping into the wallet address, specifies a wallet address of 0 length";
|
||||
}
|
||||
else
|
||||
{
|
||||
err_stream << "Could not convert the wallet address string, check it is correct, value=";
|
||||
err_stream.write(value, value_len);
|
||||
err_stream << "Could not convert the wallet address string, check it is correct, value=" << value;
|
||||
}
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
|
@ -426,14 +455,14 @@ bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, char co
|
|||
int max_value_len = lns::GENERIC_VALUE_MAX;
|
||||
bool value_require_exact_len = true;
|
||||
if (type == static_cast<uint16_t>(mapping_type::lokinet)) max_value_len = (LOKINET_ADDRESS_BINARY_LENGTH * 2);
|
||||
else if (type == static_cast<uint16_t>(mapping_type::messenger)) max_value_len = (MESSENGER_PUBLIC_KEY_BINARY_LENGTH * 2);
|
||||
else if (type == static_cast<uint16_t>(mapping_type::session)) max_value_len = (SESSION_PUBLIC_KEY_BINARY_LENGTH * 2);
|
||||
else value_require_exact_len = false;
|
||||
|
||||
if (!check_lengths(type, value, value_len, max_value_len, value_require_exact_len, reason))
|
||||
if (!check_lengths(type, value, max_value_len, value_require_exact_len, reason))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == static_cast<uint16_t>(mapping_type::blockchain))
|
||||
if (type == static_cast<uint16_t>(mapping_type::wallet))
|
||||
{
|
||||
if (blob)
|
||||
{
|
||||
|
@ -441,51 +470,75 @@ bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, char co
|
|||
memcpy(blob->buffer.data(), &addr_info.address, blob->len);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (type == static_cast<uint16_t>(mapping_type::lokinet))
|
||||
{
|
||||
// NOTE: Check value is hex
|
||||
if ((value_len % 2) != 0)
|
||||
if (value.size() != 52)
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "The value=";
|
||||
err_stream.write(value, value_len);
|
||||
err_stream << ", should be a hex string that has an even length to be convertible back into binary, length=" << value_len;
|
||||
err_stream << "The lokinet value=" << value << ", should be a 52 char base32z string, length=" << value.size();
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int val_index = 0; val_index < value_len; val_index += 2)
|
||||
crypto::ed25519_public_key pkey;
|
||||
if (!base32z::decode(value, pkey))
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "The value=" << value << ", was not a decodable base32z value.";
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blob)
|
||||
{
|
||||
blob->len = sizeof(pkey);
|
||||
memcpy(blob->buffer.data(), pkey.data, blob->len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: Check value is hex
|
||||
if ((value.size() % 2) != 0)
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "The value=" << value << ", should be a hex string that has an even length to be convertible back into binary, length=" << value.size();
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t val_index = 0; val_index < value.size(); val_index += 2)
|
||||
{
|
||||
char a = value[val_index];
|
||||
char b = value[val_index + 1];
|
||||
if (loki::char_is_hex(a) && loki::char_is_hex(b))
|
||||
if (hex::char_is_hex(a) && hex::char_is_hex(b))
|
||||
{
|
||||
if (blob) // NOTE: Given blob, write the binary output
|
||||
blob->buffer.data()[blob->len++] = loki::from_hex_pair(a, b);
|
||||
blob->buffer.data()[blob->len++] = hex::from_hex_pair(a, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=" << type <<", specifies name -> value mapping where the value is not a hex string given value=";
|
||||
err_stream.write(value, value_len);
|
||||
err_stream << "LNS type=" << type <<", specifies name -> value mapping where the value is not a hex string given value=" << value;
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == static_cast<uint16_t>(mapping_type::messenger))
|
||||
if (type == static_cast<uint16_t>(mapping_type::session))
|
||||
{
|
||||
if (!(value[0] == '0' && value[1] == '5')) // NOTE: Messenger public keys are 33 bytes, with the first byte being 0x05 and the remaining 32 being the public key.
|
||||
if (!(value[0] == '0' && value[1] == '5')) // NOTE: Session public keys are 33 bytes, with the first byte being 0x05 and the remaining 32 being the public key.
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << "LNS type=messenger, specifies mapping from name -> ed25519 key where the key is not prefixed with 53 (0x05), prefix=";
|
||||
err_stream << std::to_string(value[0]) << " (" << value[0] << "), given ed25519=";
|
||||
err_stream.write(value, value_len);
|
||||
err_stream << "LNS type=session, specifies mapping from name -> ed25519 key where the key is not prefixed with 53 (0x05), prefix=" << std::to_string(value[0]) << " (" << value[0] << "), given ed25519=" << value;
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
|
@ -495,30 +548,29 @@ bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, char co
|
|||
return true;
|
||||
}
|
||||
|
||||
bool validate_lns_value_binary(uint16_t type, char const *value, int value_len, std::string *reason)
|
||||
bool validate_lns_value_binary(uint16_t type, std::string const &value, std::string *reason)
|
||||
{
|
||||
int max_value_len = lns::GENERIC_VALUE_MAX;
|
||||
bool value_require_exact_len = true;
|
||||
if (type == static_cast<uint16_t>(mapping_type::lokinet)) max_value_len = LOKINET_ADDRESS_BINARY_LENGTH;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::messenger)) max_value_len = MESSENGER_PUBLIC_KEY_BINARY_LENGTH;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::blockchain)) max_value_len = sizeof(cryptonote::account_public_address);
|
||||
if (type == static_cast<uint16_t>(mapping_type::lokinet)) max_value_len = LOKINET_ADDRESS_BINARY_LENGTH;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::session)) max_value_len = SESSION_PUBLIC_KEY_BINARY_LENGTH;
|
||||
else if (type == static_cast<uint16_t>(mapping_type::wallet)) max_value_len = sizeof(cryptonote::account_public_address);
|
||||
else value_require_exact_len = false;
|
||||
|
||||
if (!check_lengths(type, value, value_len, max_value_len, value_require_exact_len, reason))
|
||||
if (!check_lengths(type, value, max_value_len, value_require_exact_len, reason))
|
||||
return false;
|
||||
|
||||
if (type == static_cast<uint16_t>(lns::mapping_type::blockchain))
|
||||
if (type == static_cast<uint16_t>(lns::mapping_type::wallet))
|
||||
{
|
||||
// TODO(doyle): Better address validation? Is it a valid address, is it a valid nettype address?
|
||||
cryptonote::account_public_address address;
|
||||
memcpy(&address, value, sizeof(address));
|
||||
memcpy(&address, value.data(), sizeof(address));
|
||||
if (!(crypto::check_key(address.m_spend_public_key) && crypto::check_key(address.m_view_public_key)))
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
std::stringstream err_stream;
|
||||
err_stream << "LNS type=" << type << ", specifies mapping from name -> wallet address where the wallet address's blob does not generate valid public spend/view keys";
|
||||
err_stream.write(value, value_len);
|
||||
err_stream << "LNS type=" << type << ", specifies mapping from name -> wallet address where the wallet address's blob, does not generate valid public spend/view keys";
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
|
@ -537,7 +589,7 @@ static bool validate_against_previous_mapping(lns::name_system_db const &lns_db,
|
|||
{
|
||||
std::stringstream err_stream;
|
||||
crypto::hash expected_prev_txid = crypto::null_hash;
|
||||
if (lns::mapping_record mapping = lns_db.get_mapping(data.type, data.name.data(), data.name.size()))
|
||||
if (lns::mapping_record mapping = lns_db.get_mapping(data.type, data.name))
|
||||
{
|
||||
if (data.type != static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
{
|
||||
|
@ -639,7 +691,7 @@ bool name_system_db::validate_lns_tx(uint8_t hf_version, uint64_t blockchain_hei
|
|||
return false;
|
||||
}
|
||||
|
||||
if (entry->type >= static_cast<uint16_t>(lns::mapping_type::start_reserved) && entry->type <= static_cast<uint16_t>(mapping_type::end_reserved))
|
||||
if (entry->type >= static_cast<uint16_t>(lns::mapping_type::start_unusable_range) && entry->type <= static_cast<uint16_t>(mapping_type::end_unusable_range))
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
|
@ -648,18 +700,18 @@ bool name_system_db::validate_lns_tx(uint8_t hf_version, uint64_t blockchain_hei
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t burn = cryptonote::get_burned_amount_from_tx_extra(tx.extra);
|
||||
if (!validate_lns_name(entry->type, entry->name.data(), static_cast<int>(entry->name.size()), reason))
|
||||
if (!validate_lns_name(entry->type, entry->name, reason))
|
||||
return false;
|
||||
|
||||
if (!validate_lns_value_binary(entry->type, entry->value.data(), static_cast<int>(entry->value.size()), reason))
|
||||
if (!validate_lns_value_binary(entry->type, entry->value, reason))
|
||||
return false;
|
||||
|
||||
if (!validate_against_previous_mapping(*this, blockchain_height, tx, *entry, reason))
|
||||
return false;
|
||||
|
||||
uint64_t const burn_required = burn_requirement_in_atomic_loki(hf_version);
|
||||
auto lns_type = static_cast<mapping_type>(entry->type);
|
||||
uint64_t const burn_required = burn_requirement_in_atomic_loki(hf_version, mapping_type_to_burn_type(lns_type));
|
||||
if (burn != burn_required)
|
||||
{
|
||||
if (reason)
|
||||
|
@ -684,9 +736,7 @@ bool validate_mapping_type(std::string const &type, uint16_t *mapping_type, std:
|
|||
}
|
||||
|
||||
uint16_t mapping_type_ = 0;
|
||||
if (type_lowered == "blockchain") mapping_type_ = static_cast<uint16_t>(lns::mapping_type::blockchain);
|
||||
else if (type_lowered == "lokinet") mapping_type_ = static_cast<uint16_t>(lns::mapping_type::lokinet);
|
||||
else if (type_lowered == "messenger") mapping_type_ = static_cast<uint16_t>(lns::mapping_type::messenger);
|
||||
if (type_lowered == "session") mapping_type_ = static_cast<uint16_t>(lns::mapping_type::session);
|
||||
else
|
||||
{
|
||||
try
|
||||
|
@ -694,14 +744,14 @@ bool validate_mapping_type(std::string const &type, uint16_t *mapping_type, std:
|
|||
size_t value = std::stoul(type_lowered);
|
||||
if (value > std::numeric_limits<uint16_t>::max())
|
||||
{
|
||||
if (reason) *reason = "LNS custom type specifies value too large, must be from 0-65536: " + std::to_string(value);
|
||||
if (reason) *reason = "LNS type specifies value too large, must be from 0-65535: " + std::to_string(value);
|
||||
return false;
|
||||
}
|
||||
mapping_type_ = static_cast<uint16_t>(value);
|
||||
}
|
||||
catch (std::exception const &)
|
||||
{
|
||||
if (reason) *reason = "Failed to convert custom lns mapping argument (was not proper integer, or not one of the recognised arguments blockchain, lokinet, messenger), string was: " + type;
|
||||
if (reason) *reason = "Failed to convert lns mapping (was not proper integer, or not one of the recognised: \"session\"), string was=" + type;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -763,11 +813,14 @@ bool name_system_db::init(cryptonote::network_type nettype, sqlite3 *db, uint64_
|
|||
char constexpr GET_SETTINGS_SQL[] = R"(SELECT * FROM "settings" WHERE "id" = 0)";
|
||||
char constexpr GET_USER_BY_KEY_SQL[] = R"(SELECT * FROM "user" WHERE "public_key" = ?)";
|
||||
char constexpr GET_USER_BY_ID_SQL[] = R"(SELECT * FROM "user" WHERE "id" = ?)";
|
||||
char constexpr GET_MAPPINGS_BY_USER_SQL[] = R"(SELECT * FROM "mappings" WHERE "user_id" = ?)";
|
||||
char constexpr GET_MAPPINGS_ON_HEIGHT_AND_NEWER_SQL[] = R"(SELECT * FROM mappings WHERE "register_height" >= ?)";
|
||||
char constexpr GET_MAPPINGS_ON_HEIGHT_AND_NEWER_SQL[] = R"(SELECT * FROM "mappings" WHERE "register_height" >= ?)";
|
||||
char constexpr SAVE_SETTINGS_SQL[] = R"(INSERT OR REPLACE INTO "settings" ("rowid", "top_height", "top_hash", "version") VALUES (1,?,?,?))";
|
||||
char constexpr SAVE_MAPPING_SQL[] = R"(INSERT OR REPLACE INTO "mappings" ("type", "name", "value", "txid", "prev_txid", "register_height", "user_id") VALUES (?,?,?,?,?,?,?))";
|
||||
char constexpr SAVE_USER_SQL[] = R"(INSERT INTO "user" ("public_key") VALUES (?);)";
|
||||
char constexpr GET_MAPPINGS_BY_USER_SQL[] = R"(SELECT * FROM "mappings" JOIN "user" ON "mappings"."user_id" = "user"."id" WHERE "public_key" = ?)";
|
||||
char constexpr GET_MAPPING_BY_NAME_AND_TYPE_SQL[] = R"(SELECT * FROM "mappings" JOIN "user" ON "mappings"."user_id" = "user"."id" WHERE "type" = ? AND "name" = ?)";
|
||||
|
||||
sqlite3_stmt *test;
|
||||
|
||||
if (!build_default_tables(db))
|
||||
return false;
|
||||
|
@ -782,6 +835,7 @@ bool name_system_db::init(cryptonote::network_type nettype, sqlite3 *db, uint64_
|
|||
!sql_compile_statement(db, PRUNE_MAPPINGS_SQL, loki::array_count(PRUNE_MAPPINGS_SQL), &prune_mappings_sql) ||
|
||||
!sql_compile_statement(db, PRUNE_USERS_SQL, loki::array_count(PRUNE_USERS_SQL), &prune_users_sql) ||
|
||||
!sql_compile_statement(db, GET_MAPPINGS_BY_USER_SQL, loki::array_count(GET_MAPPINGS_BY_USER_SQL), &get_mappings_by_user_sql) ||
|
||||
!sql_compile_statement(db, GET_MAPPING_BY_NAME_AND_TYPE_SQL, loki::array_count(GET_MAPPING_BY_NAME_AND_TYPE_SQL), &get_mapping_by_name_and_type_sql) ||
|
||||
!sql_compile_statement(db, GET_MAPPINGS_ON_HEIGHT_AND_NEWER_SQL, loki::array_count(GET_MAPPINGS_ON_HEIGHT_AND_NEWER_SQL), &get_mappings_on_height_and_newer_sql)
|
||||
)
|
||||
{
|
||||
|
@ -1083,27 +1137,22 @@ user_record name_system_db::get_user_by_id(int64_t user_id) const
|
|||
return result;
|
||||
}
|
||||
|
||||
mapping_record name_system_db::get_mapping(uint16_t type, char const *name, size_t name_len) const
|
||||
mapping_record name_system_db::get_mapping(uint16_t type, std::string const &name) const
|
||||
{
|
||||
sqlite3_stmt *statement = get_mapping_sql;
|
||||
sqlite3_clear_bindings(statement);
|
||||
sqlite3_bind_int(statement, 1 /*sql param index*/, type);
|
||||
sqlite3_bind_text(statement, 2 /*sql param index*/, name, name_len, nullptr /*destructor*/);
|
||||
sqlite3_bind_text(statement, 2 /*sql param index*/, name.data(), name.size(), nullptr /*destructor*/);
|
||||
|
||||
mapping_record result = {};
|
||||
result.loaded = sql_run_statement(nettype, lns_sql_type::get_mapping, statement, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
mapping_record name_system_db::get_mapping(uint16_t type, std::string const &name) const
|
||||
{
|
||||
mapping_record result = get_mapping(type, name.data(), name.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<mapping_record> name_system_db::get_mappings_by_user(crypto::ed25519_public_key const &key) const
|
||||
{
|
||||
std::vector<mapping_record> result = {};
|
||||
#if 0
|
||||
if (lns::user_record user = get_user_by_key(key))
|
||||
{
|
||||
sqlite3_stmt *statement = get_mappings_by_user_sql;
|
||||
|
@ -1111,6 +1160,23 @@ std::vector<mapping_record> name_system_db::get_mappings_by_user(crypto::ed25519
|
|||
sqlite3_bind_int(statement, 1 /*sql param index*/, user.id);
|
||||
sql_run_statement(nettype, lns_sql_type::get_mappings_by_user, statement, &result);
|
||||
}
|
||||
#else
|
||||
sqlite3_stmt *statement = get_mappings_by_user_sql;
|
||||
sqlite3_clear_bindings(statement);
|
||||
sqlite3_bind_blob(statement, 1 /*sql param index*/, key.data, sizeof(key), nullptr /*destructor*/);
|
||||
sql_run_statement(nettype, lns_sql_type::get_mappings_by_user, statement, &result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
mapping_and_user_record name_system_db::get_mapping_by_name_and_type(mapping_type type, std::string const &name) const
|
||||
{
|
||||
mapping_and_user_record result = {};
|
||||
sqlite3_stmt *statement = get_mapping_by_name_and_type_sql;
|
||||
sqlite3_clear_bindings(statement);
|
||||
sqlite3_bind_int(statement, 1 /*sql param index*/, static_cast<uint16_t>(type));
|
||||
sqlite3_bind_text(statement, 2 /*sql param index*/, name.data(), name.size(), nullptr /*destructor*/);
|
||||
sql_run_statement(nettype, lns_sql_type::get_mapping_by_name_and_type, statement, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "crypto/crypto.h"
|
||||
#include "cryptonote_config.h"
|
||||
#include "cryptonote_basic/tx_extra.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -15,19 +14,20 @@ struct checkpoint_t;
|
|||
struct block;
|
||||
struct transaction;
|
||||
struct account_address;
|
||||
struct tx_extra_loki_name_system;
|
||||
class Blockchain;
|
||||
}; // namespace cryptonote
|
||||
|
||||
namespace lns
|
||||
{
|
||||
|
||||
constexpr uint64_t BLOCKCHAIN_NAME_MAX = 96;
|
||||
constexpr uint64_t LOKINET_DOMAIN_NAME_MAX = 253;
|
||||
constexpr uint64_t LOKINET_ADDRESS_BINARY_LENGTH = sizeof(crypto::ed25519_public_key);
|
||||
constexpr uint64_t MESSENGER_DISPLAY_NAME_MAX = 64;
|
||||
constexpr uint64_t MESSENGER_PUBLIC_KEY_BINARY_LENGTH = 1 + sizeof(crypto::ed25519_public_key); // Messenger keys at prefixed with 0x05 + ed25519 key
|
||||
constexpr uint64_t GENERIC_NAME_MAX = 255;
|
||||
constexpr uint64_t GENERIC_VALUE_MAX = 255;
|
||||
constexpr size_t WALLET_NAME_MAX = 96;
|
||||
constexpr size_t LOKINET_DOMAIN_NAME_MAX = 253;
|
||||
constexpr size_t LOKINET_ADDRESS_BINARY_LENGTH = sizeof(crypto::ed25519_public_key);
|
||||
constexpr size_t SESSION_DISPLAY_NAME_MAX = 64;
|
||||
constexpr size_t SESSION_PUBLIC_KEY_BINARY_LENGTH = 1 + sizeof(crypto::ed25519_public_key); // Session keys at prefixed with 0x05 + ed25519 key
|
||||
constexpr size_t GENERIC_NAME_MAX = 255;
|
||||
constexpr size_t GENERIC_VALUE_MAX = 255;
|
||||
|
||||
struct lns_value
|
||||
{
|
||||
|
@ -35,14 +35,33 @@ struct lns_value
|
|||
size_t len;
|
||||
};
|
||||
|
||||
uint64_t burn_requirement_in_atomic_loki(uint8_t hf_version);
|
||||
enum struct mapping_type : uint16_t
|
||||
{
|
||||
session = 0,
|
||||
wallet = 1,
|
||||
lokinet = 2,
|
||||
start_unusable_range = 3,
|
||||
end_unusable_range = 64,
|
||||
};
|
||||
|
||||
enum struct burn_type
|
||||
{
|
||||
none,
|
||||
lokinet_1year,
|
||||
session,
|
||||
wallet,
|
||||
custom,
|
||||
};
|
||||
|
||||
burn_type mapping_type_to_burn_type(mapping_type in);
|
||||
uint64_t burn_requirement_in_atomic_loki(uint8_t hf_version, burn_type type);
|
||||
sqlite3 *init_loki_name_system(char const *file_path);
|
||||
uint64_t lokinet_expiry_blocks(cryptonote::network_type nettype, uint64_t *renew_window = nullptr);
|
||||
bool validate_lns_name(uint16_t type, char const *name, int name_len, std::string *reason = nullptr);
|
||||
bool validate_lns_name(uint16_t type, std::string const &name, std::string *reason = nullptr);
|
||||
|
||||
// blob: if set, validate_lns_value will convert the value into the binary format suitable for storing into the LNS DB.
|
||||
bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, char const *value, int value_len, lns_value *blob = nullptr, std::string *reason = nullptr);
|
||||
bool validate_lns_value_binary(uint16_t type, char const *value, int value_len, std::string *reason = nullptr);
|
||||
bool validate_lns_value(cryptonote::network_type nettype, uint16_t type, std::string const &value, lns_value *blob = nullptr, std::string *reason = nullptr);
|
||||
bool validate_lns_value_binary(uint16_t type, std::string const &value, std::string *reason = nullptr);
|
||||
|
||||
bool validate_mapping_type(std::string const &type, uint16_t *mapping_type, std::string *reason);
|
||||
|
||||
|
@ -85,6 +104,13 @@ struct mapping_record
|
|||
crypto::hash prev_txid;
|
||||
};
|
||||
|
||||
struct mapping_and_user_record
|
||||
{
|
||||
operator bool() const { return mapping.loaded; }
|
||||
mapping_record mapping;
|
||||
crypto::ed25519_public_key owner;
|
||||
};
|
||||
|
||||
struct name_system_db
|
||||
{
|
||||
bool init (cryptonote::network_type nettype, sqlite3 *db, uint64_t top_height, crypto::hash const &top_hash);
|
||||
|
@ -101,11 +127,11 @@ struct name_system_db
|
|||
|
||||
user_record get_user_by_key (crypto::ed25519_public_key const &key) const;
|
||||
user_record get_user_by_id (int64_t user_id) const;
|
||||
mapping_record get_mapping (uint16_t type, char const *name, size_t name_len) const;
|
||||
mapping_record get_mapping (uint16_t type, std::string const &name) const;
|
||||
|
||||
// return: Array of records in sorted order by their register height, ties dealt by name lexicographiclly
|
||||
std::vector<mapping_record> get_mappings_by_user(crypto::ed25519_public_key const &key) const;
|
||||
mapping_and_user_record get_mapping_by_name_and_type(mapping_type type, std::string const &name) const;
|
||||
settings_record get_settings () const;
|
||||
|
||||
bool validate_lns_tx(uint8_t hf_version, uint64_t blockchain_height, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system *entry = nullptr, std::string *reason = nullptr) const;
|
||||
|
@ -127,6 +153,7 @@ private:
|
|||
sqlite3_stmt *prune_users_sql = nullptr;
|
||||
sqlite3_stmt *get_mappings_by_user_sql = nullptr;
|
||||
sqlite3_stmt *get_mappings_on_height_and_newer_sql = nullptr;
|
||||
sqlite3_stmt *get_mapping_by_name_and_type_sql = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "sn_network.h"
|
||||
#include "bt_serialize.h"
|
||||
#include "common/loki.h"
|
||||
#include "common/hex.h"
|
||||
#include <ostream>
|
||||
#ifdef __cpp_lib_string_view
|
||||
#include <string_view>
|
||||
|
@ -934,7 +934,7 @@ void SNNetwork::proxy_to_worker(size_t conn_index, std::list<zmq::message_t> &&p
|
|||
const char *pubkey_hex = parts.back().gets("User-Id");
|
||||
auto len = std::strlen(pubkey_hex);
|
||||
assert(len == 66 && (pubkey_hex[0] == 'S' || pubkey_hex[0] == 'C') && pubkey_hex[1] == ':');
|
||||
pubkey = loki::from_hex(pubkey_hex + 2, pubkey_hex + 66);
|
||||
pubkey = hex::from_hex(pubkey_hex + 2, pubkey_hex + 66);
|
||||
remote_is_sn = pubkey_hex[0] == 'S';
|
||||
} catch (...) {
|
||||
SN_LOG(error, "Internal error: socket User-Id not set or invalid; dropping message");
|
||||
|
|
|
@ -45,6 +45,7 @@ using namespace epee;
|
|||
#include "common/util.h"
|
||||
#include "common/perf_timer.h"
|
||||
#include "common/random.h"
|
||||
#include "common/base32z.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "cryptonote_basic/account.h"
|
||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||
|
@ -3354,26 +3355,28 @@ namespace cryptonote
|
|||
|
||||
for (uint16_t type : request.types)
|
||||
{
|
||||
if (lns::mapping_record mapping = db.get_mapping(type, request.name))
|
||||
if (lns::mapping_and_user_record record = db.get_mapping_by_name_and_type(static_cast<lns::mapping_type>(type), request.name))
|
||||
{
|
||||
if (lns::user_record user = db.get_user_by_id(mapping.user_id))
|
||||
res.entries.emplace_back();
|
||||
COMMAND_RPC_GET_LNS_NAMES_TO_OWNERS::response_entry &entry = res.entries.back();
|
||||
entry.entry_index = request_index;
|
||||
entry.type = type;
|
||||
entry.owner = epee::string_tools::pod_to_hex(record.owner);
|
||||
|
||||
if (static_cast<lns::mapping_type>(type) == lns::mapping_type::lokinet)
|
||||
{
|
||||
res.entries.emplace_back();
|
||||
COMMAND_RPC_GET_LNS_NAMES_TO_OWNERS::response_entry &entry = res.entries.back();
|
||||
entry.entry_index = request_index;
|
||||
entry.type = type;
|
||||
entry.owner = epee::string_tools::pod_to_hex(user.key);
|
||||
entry.pubkey = mapping.value;
|
||||
entry.register_height = mapping.register_height;
|
||||
entry.txid = epee::string_tools::pod_to_hex(mapping.txid);
|
||||
entry.prev_txid = epee::string_tools::pod_to_hex(mapping.prev_txid);
|
||||
char buf[64] = {};
|
||||
base32z::encode(record.mapping.value, buf);
|
||||
entry.value = std::string(buf) + ".loki";
|
||||
}
|
||||
else
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Invalid mapping for name = " + request.name + ", specifies non-existent user with id = " + std::to_string(mapping.user_id);
|
||||
return false;
|
||||
entry.value = record.mapping.value;
|
||||
}
|
||||
|
||||
entry.register_height = record.mapping.register_height;
|
||||
entry.txid = epee::string_tools::pod_to_hex(record.mapping.txid);
|
||||
entry.prev_txid = epee::string_tools::pod_to_hex(record.mapping.prev_txid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3408,7 +3411,18 @@ namespace cryptonote
|
|||
COMMAND_RPC_GET_LNS_OWNERS_TO_NAMES::response_mapping &mapping = entry.mappings.back();
|
||||
mapping.type = db_mapping.type;
|
||||
mapping.name = db_mapping.name;
|
||||
mapping.pubkey = db_mapping.value;
|
||||
|
||||
if (static_cast<lns::mapping_type>(mapping.type) == lns::mapping_type::lokinet)
|
||||
{
|
||||
char buf[64] = {};
|
||||
base32z::encode(db_mapping.value, buf);
|
||||
mapping.value = std::string(buf) + ".loki";
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping.value = db_mapping.value;
|
||||
}
|
||||
|
||||
mapping.register_height = db_mapping.register_height;
|
||||
mapping.txid = epee::string_tools::pod_to_hex(db_mapping.txid);
|
||||
mapping.prev_txid = epee::string_tools::pod_to_hex(db_mapping.prev_txid);
|
||||
|
|
|
@ -3416,16 +3416,16 @@ constexpr char const CORE_RPC_STATUS_TX_LONG_POLL_MAX_CONNECTIONS[] = "Daemon ma
|
|||
};
|
||||
|
||||
LOKI_RPC_DOC_INTROSPECT
|
||||
// Get the name mapping for a Loki Name Service entry. Loki supports mappings
|
||||
// from the Blockchain, Lokinet, Messenger and custom types.
|
||||
// Get the name mapping for a Loki Name Service entry. Loki currently supports mappings
|
||||
// for Session.
|
||||
struct COMMAND_RPC_GET_LNS_NAMES_TO_OWNERS
|
||||
{
|
||||
static size_t const MAX_REQUEST_ENTRIES = 256;
|
||||
static size_t const MAX_TYPE_REQUEST_ENTRIES = 16;
|
||||
struct request_entry
|
||||
{
|
||||
std::string name; // The name to resolve to a public key via Loki Name Service
|
||||
std::vector<uint16_t> types; // [0-2] for Blockchain, Lokinet and Messenger and [65-65536] for custom types, you may request up to 16 types
|
||||
std::string name; // The name to resolve to a public key via Loki Name Service
|
||||
std::vector<uint16_t> types; // Set 0 for Session. In future updates more mapping types will be available.
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(types)
|
||||
|
@ -3442,18 +3442,18 @@ constexpr char const CORE_RPC_STATUS_TX_LONG_POLL_MAX_CONNECTIONS[] = "Daemon ma
|
|||
|
||||
struct response_entry
|
||||
{
|
||||
uint64_t entry_index; // The index in request_entry's `entries` array that was resolved via Loki Name Service
|
||||
uint16_t type; // The type of Loki Name Service entry that the owner owns.
|
||||
std::string owner; // The ed25519 public key that purchased the Loki Name Service entry.
|
||||
std::string pubkey; // The public key that was resolved from the given name
|
||||
uint64_t register_height; // The height that this Loki Name Service entry was purchased on the Blockchain
|
||||
std::string txid; // The txid of who purchased the mapping (only applicable to Lokinet and if the Lokinet entry previously existed), null hash if not applicable
|
||||
std::string prev_txid; // The previous txid that purchased the mapping (only applicable to Lokinet and if the Lokinet entry previously existed), null hash if not applicable
|
||||
uint64_t entry_index; // The index in request_entry's `entries` array that was resolved via Loki Name Service.
|
||||
uint16_t type; // The type of Loki Name Service entry that the owner owns.
|
||||
std::string owner; // The ed25519 public key that purchased the Loki Name Service entry.
|
||||
std::string value; // The value that the name maps to.
|
||||
uint64_t register_height; // The height that this Loki Name Service entry was purchased on the Blockchain.
|
||||
std::string txid; // The txid of who purchased the mapping, null hash if not applicable.
|
||||
std::string prev_txid; // The previous txid that purchased the mapping, null hash if not applicable.
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(entry_index)
|
||||
KV_SERIALIZE(type)
|
||||
KV_SERIALIZE(owner)
|
||||
KV_SERIALIZE(pubkey)
|
||||
KV_SERIALIZE(value)
|
||||
KV_SERIALIZE(register_height)
|
||||
KV_SERIALIZE(txid)
|
||||
KV_SERIALIZE(prev_txid)
|
||||
|
@ -3472,9 +3472,9 @@ constexpr char const CORE_RPC_STATUS_TX_LONG_POLL_MAX_CONNECTIONS[] = "Daemon ma
|
|||
};
|
||||
|
||||
LOKI_RPC_DOC_INTROSPECT
|
||||
// Get all the name mappings for the queried owner. The owner should a ED25519
|
||||
// public key, by default this is the purchaser's wallet spend key used to
|
||||
// seed an ED25519 key.
|
||||
// Get all the name mappings for the queried owner. The owner should be
|
||||
// a ed25519 public key; by default this is the public key of an ed25519
|
||||
// keypair derived using the wallet's secret spend key as the seed value.
|
||||
struct COMMAND_RPC_GET_LNS_OWNERS_TO_NAMES
|
||||
{
|
||||
static size_t const MAX_REQUEST_ENTRIES = 256;
|
||||
|
@ -3488,16 +3488,16 @@ constexpr char const CORE_RPC_STATUS_TX_LONG_POLL_MAX_CONNECTIONS[] = "Daemon ma
|
|||
|
||||
struct response_mapping
|
||||
{
|
||||
uint16_t type; // The cateogry the Loki Name Service entry belongs to (blockchain = 0, lokinet = 1, messenger = 2, otherwise custom)
|
||||
uint16_t type; // The category the Loki Name Service entry belongs to, currently only Session whose value is 0.
|
||||
std::string name; // The ed25519 public key that purchased the Loki Name Service entry.
|
||||
std::string pubkey; // The public key that the name maps to.
|
||||
std::string value; // The value that the name maps to
|
||||
uint64_t register_height; // The height that this Loki Name Service entry was purchased on the Blockchain.
|
||||
std::string txid; // The height that this Loki Name Service entry was purchased on the Blockchain.
|
||||
std::string prev_txid; // The previous txid that purchased the mapping (only applicable to Lokinet and if the Lokinet entry previously existed), null hash if not applicable
|
||||
std::string txid; // The txid of who purchases the mapping, null hash if not applicable
|
||||
std::string prev_txid; // The previous txid that purchased the mapping, null hash if not applicable.
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(type)
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(pubkey)
|
||||
KV_SERIALIZE(value)
|
||||
KV_SERIALIZE(txid)
|
||||
KV_SERIALIZE(prev_txid)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "common/dns_utils.h"
|
||||
#include "common/base58.h"
|
||||
#include "common/scoped_message_writer.h"
|
||||
#include "common/hex.h"
|
||||
#include "common/loki_integration_test_hooks.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
||||
#include "cryptonote_core/service_node_voting.h"
|
||||
|
@ -267,8 +268,8 @@ namespace
|
|||
const char* USAGE_STAKE("stake [index=<N1>[,<N2>,...]] [<priority>] <service node pubkey> <amount|percent%>");
|
||||
const char* USAGE_REQUEST_STAKE_UNLOCK("request_stake_unlock <service_node_pubkey>");
|
||||
const char* USAGE_PRINT_LOCKED_STAKES("print_locked_stakes");
|
||||
const char* USAGE_BUY_LNS_MAPPING("buy_lns_mapping [index=<N1>[,<N2>,...]] [<priority>] [owner] (blockchain|lokinet|messenger|<custom_type_as_number>) \"<name>\" <value>");
|
||||
const char* USAGE_PRINT_LNS_OWNERS_TO_NAMES("print_lns_owners_to_names [<64 hex character ed25519 key>]");
|
||||
const char* USAGE_BUY_LNS_MAPPING("buy_lns_mapping [index=<N1>[,<N2>,...]] [<priority>] [owner] \"<name>\" <value>");
|
||||
const char* USAGE_PRINT_LNS_OWNERS_TO_NAMES("print_lns_owners_to_names [<64 hex character ed25519 public key>]");
|
||||
const char* USAGE_PRINT_LNS_NAME_TO_OWNERS("print_lns_name_to_owners [type=<N1|all>[,<N2>...]] \"name\"");
|
||||
|
||||
#if defined (LOKI_ENABLE_INTEGRATION_TEST_HOOKS)
|
||||
|
@ -3217,12 +3218,11 @@ simple_wallet::simple_wallet()
|
|||
tr(USAGE_PRINT_LOCKED_STAKES),
|
||||
tr("Print stakes currently locked on the Service Node network"));
|
||||
std::stringstream stream;
|
||||
stream << "Buy a Loki Name Service mapping. Specifying `owner` is optional and defaults to the purchasing wallet if empty or not specified. The `owner` is an ED25519 public key, by default derived from the wallet's spend key. You are able to purchase the following mappings\n\n";
|
||||
|
||||
stream << "Blockchain: (max: " << lns::BLOCKCHAIN_NAME_MAX << " bytes) map a human readable name to a wallet address\n";
|
||||
stream << "Lokinet: (max: " << lns::LOKINET_DOMAIN_NAME_MAX << " bytes) map a human readable domain name to a <public_key>.loki address on Lokinet\n";
|
||||
stream << "Messenger: (max: " << lns::MESSENGER_DISPLAY_NAME_MAX << " bytes) map a human readable name to a messenger public key for Loki Messenger\n";
|
||||
stream << "Custom: (max: " << lns::GENERIC_NAME_MAX << " bytes) map a human readable name to an arbitrary integer (note, [0-64] are currently reserved by Loki) in the database for custom applications\n";
|
||||
stream << "Buy a Loki Name Service mapping. Specifying `owner` is optional and defaults to the purchasing wallet if "
|
||||
"empty or not specified. The `owner` should be a ed25519 public key; by default this is the public key of "
|
||||
"an ed25519 keypair derived using the wallet's secret spend key as the seed value. You are currently only "
|
||||
"able to purchase Session mappings\n\n";
|
||||
stream << "Session: (max: " << lns::SESSION_DISPLAY_NAME_MAX << " bytes) map a human readable name to a Session public key.\n";
|
||||
|
||||
m_cmd_binder.set_handler("buy_lns_mapping",
|
||||
boost::bind(&simple_wallet::buy_lns_mapping, this, _1),
|
||||
|
@ -3237,8 +3237,7 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("print_lns_name_to_owners",
|
||||
boost::bind(&simple_wallet::print_lns_name_to_owners, this, _1),
|
||||
tr(USAGE_PRINT_LNS_NAME_TO_OWNERS),
|
||||
tr("Query the keys that own the Loki Name Service names, where types can be a number from [0-65536] or, \"blockchain\", \"lokinet\", \"messenger\". If type is ommitted, all loki name protocols will be queried (blockchain, lokinet and messenger only)\n"
|
||||
"You may only query 1 custom type per invocation."));
|
||||
tr("Query the ed25519 public keys that own the Loki Name System names."));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::set_variable(const std::vector<std::string> &args)
|
||||
|
@ -5721,23 +5720,6 @@ bool simple_wallet::confirm_and_send_tx(std::vector<cryptonote::address_parse_in
|
|||
worst_fee_per_byte = fee_per_byte;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
std::vector<std::pair<uint64_t, uint64_t>> nblocks = m_wallet->estimate_backlog({std::make_pair(worst_fee_per_byte, worst_fee_per_byte)});
|
||||
if (nblocks.size() != 1)
|
||||
{
|
||||
prompt << "Internal error checking for backlog. " << tr("Is this okay anyway?");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nblocks[0].first > m_wallet->get_confirm_backlog_threshold())
|
||||
prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay?")) % nblocks[0].first).str();
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
prompt << tr("Failed to check for backlog: ") << e.what() << ENDL << tr("Is this okay anyway?");
|
||||
}
|
||||
|
||||
std::string prompt_str = prompt.str();
|
||||
if (!prompt_str.empty())
|
||||
|
@ -5807,7 +5789,7 @@ bool simple_wallet::confirm_and_send_tx(std::vector<cryptonote::address_parse_in
|
|||
|
||||
if (lock_time_in_blocks > 0)
|
||||
{
|
||||
float days = lock_time_in_blocks / 720.0f;
|
||||
float days = lock_time_in_blocks / BLOCKS_EXPECTED_IN_DAYS(1.f);
|
||||
prompt << boost::format(tr(".\nThis transaction (including %s change) will unlock on block %llu, in approximately %s days (assuming 2 minutes per block)")) % cryptonote::print_money(change) % ((unsigned long long)unlock_block) % days;
|
||||
}
|
||||
|
||||
|
@ -6105,7 +6087,16 @@ bool simple_wallet::transfer_main(Transfer transfer_type, const std::vector<std:
|
|||
}
|
||||
unlock_block = bc_height + locked_blocks;
|
||||
}
|
||||
ptx_vector = m_wallet->create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices);
|
||||
|
||||
boost::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
|
||||
if (!hf_version)
|
||||
{
|
||||
fail_msg_writer() << tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
loki_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, txtype::standard, priority);
|
||||
ptx_vector = m_wallet->create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices, tx_params);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
|
@ -6573,7 +6564,6 @@ bool simple_wallet::buy_lns_mapping(const std::vector<std::string>& args)
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string const &type = local_args[0];
|
||||
std::string const &value = local_args[local_args.size() - 1];
|
||||
std::string name;
|
||||
|
||||
|
@ -6591,7 +6581,14 @@ bool simple_wallet::buy_lns_mapping(const std::vector<std::string>& args)
|
|||
std::vector<tools::wallet2::pending_tx> ptx_vector;
|
||||
try
|
||||
{
|
||||
ptx_vector = m_wallet->create_buy_lns_mapping_tx(type, owner, name, value, &reason, priority, m_current_subaddress_account, subaddr_indices);
|
||||
ptx_vector = m_wallet->create_buy_lns_mapping_tx(static_cast<uint16_t>(lns::mapping_type::session),
|
||||
owner,
|
||||
name,
|
||||
value,
|
||||
&reason,
|
||||
priority,
|
||||
m_current_subaddress_account,
|
||||
subaddr_indices);
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
tools::fail_msg_writer() << reason;
|
||||
|
@ -6681,9 +6678,9 @@ bool simple_wallet::print_lns_name_to_owners(const std::vector<std::string>& arg
|
|||
|
||||
if (entry.types.empty())
|
||||
{
|
||||
entry.types.push_back(static_cast<uint16_t>(lns::mapping_type::blockchain));
|
||||
entry.types.push_back(static_cast<uint16_t>(lns::mapping_type::wallet));
|
||||
entry.types.push_back(static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
entry.types.push_back(static_cast<uint16_t>(lns::mapping_type::messenger));
|
||||
entry.types.push_back(static_cast<uint16_t>(lns::mapping_type::session));
|
||||
}
|
||||
|
||||
boost::optional<std::string> failed;
|
||||
|
@ -6732,7 +6729,7 @@ bool simple_wallet::print_lns_owners_to_names(const std::vector<std::string>& ar
|
|||
|
||||
for (char c : arg)
|
||||
{
|
||||
if (!loki::char_is_hex(c))
|
||||
if (!hex::char_is_hex(c))
|
||||
{
|
||||
fail_msg_writer() << "arg contains a non-hex character = " << c << ", arg = " << arg;
|
||||
return false;
|
||||
|
@ -6765,7 +6762,7 @@ bool simple_wallet::print_lns_owners_to_names(const std::vector<std::string>& ar
|
|||
}
|
||||
|
||||
for (cryptonote::COMMAND_RPC_GET_LNS_OWNERS_TO_NAMES::response_mapping const &mapping : entry.mappings)
|
||||
tools::msg_writer() << "owner=" << *owner << ", height=" << mapping.register_height << ", name=\"" << mapping.name << "\", value=" << mapping.pubkey;
|
||||
tools::msg_writer() << "owner=" << *owner << ", height=" << mapping.register_height << ", name=\"" << mapping.name << "\", value=" << mapping.value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -163,8 +163,8 @@ namespace cryptonote
|
|||
bool show_payments(const std::vector<std::string> &args);
|
||||
bool show_blockchain_height(const std::vector<std::string> &args);
|
||||
|
||||
// lock_time_in_blocks: Only required if making a locked transfer, it should be the lock time specified by the sender
|
||||
// unlock_block: Only required if making a locked transfer, the block height the transaction will unlock at
|
||||
// lock_time_in_blocks: Only required if making a locked transfer, only for displaying to the user, it should be the lock time specified by the sender
|
||||
// unlock_block: Only required if lock_time_in_blocks is specified, only for displaying to the user, the height at which the transfer will unlock
|
||||
bool confirm_and_send_tx(std::vector<cryptonote::address_parse_info> const &dests, std::vector<tools::wallet2::pending_tx> &ptx_vector, bool blink, uint64_t lock_time_in_blocks = 0, uint64_t unlock_block = 0, bool called_by_mms = false);
|
||||
bool transfer_main(Transfer transfer_type, const std::vector<std::string> &args, bool called_by_mms);
|
||||
|
||||
|
|
|
@ -1516,6 +1516,15 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
|
|||
de.is_subaddress = info.is_subaddress;
|
||||
de.is_integrated = info.has_payment_id;
|
||||
dsts.push_back(de);
|
||||
cryptonote::loki_construct_tx_params tx_params;
|
||||
|
||||
boost::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
|
||||
if (!hf_version)
|
||||
{
|
||||
setStatusError(tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED);
|
||||
return transaction;
|
||||
}
|
||||
loki_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, txtype::standard, priority);
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
|
|
|
@ -262,12 +262,6 @@ static bool check_invoke(bool r, T &response, boost::optional<std::string> &fail
|
|||
return false;
|
||||
}
|
||||
|
||||
if (response.status == CORE_RPC_STATUS_BUSY)
|
||||
{
|
||||
failed = response.status;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.status != CORE_RPC_STATUS_OK)
|
||||
{
|
||||
failed = response.status;
|
||||
|
|
|
@ -7671,7 +7671,8 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
|
|||
}
|
||||
return priority;
|
||||
}
|
||||
loki_construct_tx_params wallet2::construct_params(uint8_t hf_version, txtype tx_type, uint32_t priority)
|
||||
|
||||
loki_construct_tx_params wallet2::construct_params(uint8_t hf_version, txtype tx_type, uint32_t priority, lns::burn_type lns_burn_type)
|
||||
{
|
||||
loki_construct_tx_params tx_params;
|
||||
tx_params.hf_version = hf_version;
|
||||
|
@ -7680,7 +7681,7 @@ loki_construct_tx_params wallet2::construct_params(uint8_t hf_version, txtype tx
|
|||
if (tx_type == txtype::loki_name_system)
|
||||
{
|
||||
assert(priority != tools::tx_priority_blink);
|
||||
tx_params.burn_fixed = lns::burn_requirement_in_atomic_loki(hf_version);
|
||||
tx_params.burn_fixed = lns::burn_requirement_in_atomic_loki(hf_version, lns_burn_type);
|
||||
}
|
||||
else if (priority == tools::tx_priority_blink)
|
||||
{
|
||||
|
@ -7951,12 +7952,6 @@ bool wallet2::is_output_blackballed(const std::pair<uint64_t, uint64_t> &output)
|
|||
catch (const std::exception &e) { return false; }
|
||||
}
|
||||
|
||||
static const char *ERR_MSG_NETWORK_VERSION_QUERY_FAILED = tr("Could not query the current network version, try later");
|
||||
static const char *ERR_MSG_NETWORK_HEIGHT_QUERY_FAILED = tr("Could not query the current network block height, try later: ");
|
||||
static const char *ERR_MSG_SERVICE_NODE_LIST_QUERY_FAILED = tr("Failed to query daemon for service node list");
|
||||
static const char *ERR_MSG_TOO_MANY_TXS_CONSTRUCTED = tr("Constructed too many transations, please sweep_all first");
|
||||
static const char *ERR_MSG_EXCEPTION_THROWN = tr("Exception thrown, staking process could not be completed: ");
|
||||
|
||||
wallet2::stake_result wallet2::check_stake_allowed(const crypto::public_key& sn_key, const cryptonote::address_parse_info& addr_info, uint64_t& amount, double fraction)
|
||||
{
|
||||
wallet2::stake_result result = {};
|
||||
|
@ -8165,7 +8160,8 @@ wallet2::stake_result wallet2::create_stake_tx(const crypto::public_key& service
|
|||
return result;
|
||||
}
|
||||
|
||||
auto ptx_vector = create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, unlock_at_block, priority, extra, subaddr_account, subaddr_indices, txtype::stake);
|
||||
loki_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, txtype::stake, priority);
|
||||
auto ptx_vector = create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, unlock_at_block, priority, extra, subaddr_account, subaddr_indices, tx_params);
|
||||
if (ptx_vector.size() == 1)
|
||||
{
|
||||
result.status = stake_result_status::success;
|
||||
|
@ -8401,7 +8397,8 @@ wallet2::register_service_node_result wallet2::create_register_service_node_tx(c
|
|||
cryptonote::address_parse_info dest = {};
|
||||
dest.address = address;
|
||||
|
||||
auto ptx_vector = create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, 0 /* unlock_time */, priority, extra, subaddr_account, subaddr_indices, txtype::stake);
|
||||
loki_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, txtype::stake, priority);
|
||||
auto ptx_vector = create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, 0 /* unlock_time */, priority, extra, subaddr_account, subaddr_indices, tx_params);
|
||||
if (ptx_vector.size() == 1)
|
||||
{
|
||||
result.status = register_service_node_result_status::success;
|
||||
|
@ -8554,11 +8551,11 @@ std::vector<wallet2::pending_tx> wallet2::create_buy_lns_mapping_tx(uint16_t typ
|
|||
uint32_t account_index,
|
||||
std::set<uint32_t> subaddr_indices)
|
||||
{
|
||||
if (!lns::validate_lns_name(type, name.data(), name.size(), reason))
|
||||
if (!lns::validate_lns_name(type, name, reason))
|
||||
return {};
|
||||
|
||||
lns::lns_value value_blob;
|
||||
if (!lns::validate_lns_value(nettype(), type, value.data(), value.size(), &value_blob, reason))
|
||||
if (!lns::validate_lns_value(nettype(), type, value, &value_blob, reason))
|
||||
return {};
|
||||
|
||||
if (priority == tools::tx_priority_blink)
|
||||
|
@ -8583,7 +8580,6 @@ std::vector<wallet2::pending_tx> wallet2::create_buy_lns_mapping_tx(uint16_t typ
|
|||
}
|
||||
|
||||
crypto::hash prev_txid = crypto::null_hash;
|
||||
if (type == static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
{
|
||||
std::vector<cryptonote::COMMAND_RPC_GET_LNS_NAMES_TO_OWNERS::request_entry> request = {};
|
||||
{
|
||||
|
@ -8597,7 +8593,7 @@ std::vector<wallet2::pending_tx> wallet2::create_buy_lns_mapping_tx(uint16_t typ
|
|||
std::vector<cryptonote::COMMAND_RPC_GET_LNS_NAMES_TO_OWNERS::response_entry> response = get_lns_names_to_owners(request, failed);
|
||||
if (failed)
|
||||
{
|
||||
if (reason) *reason = "Failed to query previous owner for lokinet entry, reason=" + *failed;
|
||||
if (reason) *reason = "Failed to query previous owner for LNS entry, reason=" + *failed;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -8616,10 +8612,18 @@ std::vector<wallet2::pending_tx> wallet2::create_buy_lns_mapping_tx(uint16_t typ
|
|||
}
|
||||
}
|
||||
|
||||
tx_extra_loki_name_system entry(pkey, type, name, value, prev_txid);
|
||||
boost::optional<uint8_t> hf_version = get_hard_fork_version();
|
||||
if (!hf_version)
|
||||
{
|
||||
if (reason) *reason = ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
tx_extra_loki_name_system entry(pkey, type, name, value, prev_txid);
|
||||
add_loki_name_system_to_tx_extra(extra, entry);
|
||||
|
||||
loki_construct_tx_params tx_params = wallet2::construct_params(*hf_version, txtype::loki_name_system, priority, lns::mapping_type_to_burn_type(static_cast<lns::mapping_type>(type)));
|
||||
auto result = create_transactions_2({} /*dests*/,
|
||||
CRYPTONOTE_DEFAULT_TX_MIXIN,
|
||||
0 /*unlock_at_block*/,
|
||||
|
@ -8627,7 +8631,7 @@ std::vector<wallet2::pending_tx> wallet2::create_buy_lns_mapping_tx(uint16_t typ
|
|||
extra,
|
||||
account_index,
|
||||
subaddr_indices,
|
||||
txtype::loki_name_system);
|
||||
tx_params);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -10354,7 +10358,7 @@ static constexpr uint64_t BURN_FEE_PLACEHOLDER = (1ULL << (6*7)) - 1;
|
|||
// This system allows for sending (almost) the entire balance, since it does
|
||||
// not generate spurious change in all txes, thus decreasing the instantaneous
|
||||
// usable balance.
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra_base, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, cryptonote::txtype tx_type)
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra_base, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, loki_construct_tx_params &tx_params)
|
||||
{
|
||||
//ensure device is let in NONE mode in any case
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
|
@ -10362,7 +10366,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
hw::reset_mode rst(hwdev);
|
||||
|
||||
auto original_dsts = dsts;
|
||||
if (tx_type == txtype::loki_name_system)
|
||||
if (tx_params.tx_type == txtype::loki_name_system)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(dsts.size() != 0, error::wallet_internal_error, "loki name system txs must not have any destinations set, has: " + std::to_string(dsts.size()));
|
||||
dsts.emplace_back(0, account_public_address{} /*address*/, false /*is_subaddress*/); // NOTE: Create a dummy dest that gets repurposed into the change output.
|
||||
|
@ -10425,18 +10429,14 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
uint64_t fixed_fee = 0;
|
||||
const uint64_t fee_quantization_mask = get_fee_quantization_mask();
|
||||
|
||||
boost::optional<uint8_t> hf_version = get_hard_fork_version();
|
||||
THROW_WALLET_EXCEPTION_IF(!hf_version, error::get_hard_fork_version_error, "Failed to query current hard fork version");
|
||||
|
||||
loki_construct_tx_params loki_tx_params = tools::wallet2::construct_params(*hf_version, tx_type, priority);
|
||||
uint64_t burn_fixed = 0, burn_percent = 0;
|
||||
// Swap these out because we don't want them present for building intermediate temporary tx
|
||||
// calculations (which we don't actually use); we'll set them again at the end before we build the
|
||||
// real transactions.
|
||||
std::swap(burn_fixed, loki_tx_params.burn_fixed);
|
||||
std::swap(burn_percent, loki_tx_params.burn_percent);
|
||||
std::swap(burn_fixed, tx_params.burn_fixed);
|
||||
std::swap(burn_percent, tx_params.burn_percent);
|
||||
bool burning = burn_fixed || burn_percent;
|
||||
THROW_WALLET_EXCEPTION_IF(burning && loki_tx_params.hf_version < HF_VERSION_FEE_BURNING, error::wallet_internal_error, "cannot construct transaction: cannot burn amounts under the current hard fork");
|
||||
THROW_WALLET_EXCEPTION_IF(burning && tx_params.hf_version < HF_VERSION_FEE_BURNING, error::wallet_internal_error, "cannot construct transaction: cannot burn amounts under the current hard fork");
|
||||
std::vector<uint8_t> extra_plus; // Copy and modified from input if modification needed
|
||||
const std::vector<uint8_t> &extra = burning ? extra_plus : extra_base;
|
||||
if (burning)
|
||||
|
@ -10455,14 +10455,14 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
needed_money = 0;
|
||||
for(auto& dt: dsts)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(0 == dt.amount && (tx_type != txtype::loki_name_system), error::zero_destination);
|
||||
THROW_WALLET_EXCEPTION_IF(0 == dt.amount && (tx_params.tx_type != txtype::loki_name_system), error::zero_destination);
|
||||
needed_money += dt.amount;
|
||||
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
|
||||
THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype);
|
||||
}
|
||||
|
||||
// throw if attempting a transaction with no money
|
||||
THROW_WALLET_EXCEPTION_IF(needed_money == 0 && (tx_type != txtype::loki_name_system), error::zero_destination);
|
||||
THROW_WALLET_EXCEPTION_IF(needed_money == 0 && (tx_params.tx_type != txtype::loki_name_system), error::zero_destination);
|
||||
|
||||
std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account);
|
||||
std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account);
|
||||
|
@ -10476,7 +10476,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
// early out if we know we can't make it anyway
|
||||
// we could also check for being within FEE_PER_KB, but if the fee calculation
|
||||
// ever changes, this might be missed, so let this go through
|
||||
const uint64_t num_outputs = tx_type == txtype::loki_name_system ? 1 : 2;
|
||||
const uint64_t num_outputs = tx_params.tx_type == txtype::loki_name_system ? 1 : 2;
|
||||
{
|
||||
uint64_t min_fee = (
|
||||
base_fee.first * estimate_rct_tx_size(1, fake_outs_count, num_outputs, extra.size()) +
|
||||
|
@ -10653,7 +10653,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
idx = pop_back(preferred_inputs);
|
||||
pop_if_present(*unused_transfers_indices, idx);
|
||||
pop_if_present(*unused_dust_indices, idx);
|
||||
} else if ((dsts.empty() || (dsts[0].amount == 0 && tx_type != txtype::loki_name_system)) && !adding_fee) {
|
||||
} else if ((dsts.empty() || (dsts[0].amount == 0 && tx_params.tx_type != txtype::loki_name_system)) && !adding_fee) {
|
||||
// NOTE: A LNS tx sets dsts[0].amount to 0, but this branch is for the
|
||||
// 2 inputs/2 outputs. We only have 1 output as LNS transactions are
|
||||
// distinguishable, so we actually want the last branch which uses unused
|
||||
|
@ -10771,7 +10771,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " <<
|
||||
tx.selected_transfers.size() << " inputs");
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, loki_tx_params);
|
||||
test_tx, test_ptx, rct_config, tx_params);
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(test_ptx.tx, txBlob.size(), base_fee, fee_percent, fixed_fee, fee_quantization_mask);
|
||||
available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0);
|
||||
|
@ -10810,7 +10810,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
LOG_PRINT_L2("We made a tx, adjusting fee and saving it, we need " << print_money(needed_fee) << " and we have " << print_money(test_ptx.fee));
|
||||
while (needed_fee > test_ptx.fee) {
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config, loki_tx_params);
|
||||
test_tx, test_ptx, rct_config, tx_params);
|
||||
txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(test_ptx.tx, txBlob.size(), base_fee, fee_percent, fixed_fee, fee_quantization_mask);
|
||||
LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) <<
|
||||
|
@ -10872,9 +10872,9 @@ skip_tx:
|
|||
// fee percent)
|
||||
if (burning)
|
||||
{
|
||||
loki_tx_params.burn_fixed = burn_fixed + tx.needed_fee * burn_percent / fee_percent;
|
||||
tx_params.burn_fixed = burn_fixed + tx.needed_fee * burn_percent / fee_percent;
|
||||
// Make sure we can't enlarge the tx because that could make it invalid:
|
||||
THROW_WALLET_EXCEPTION_IF(loki_tx_params.burn_fixed > BURN_FEE_PLACEHOLDER, error::wallet_internal_error, "attempt to burn a larger amount than is internally supported");
|
||||
THROW_WALLET_EXCEPTION_IF(tx_params.burn_fixed > BURN_FEE_PLACEHOLDER, error::wallet_internal_error, "attempt to burn a larger amount than is internally supported");
|
||||
}
|
||||
|
||||
cryptonote::transaction test_tx;
|
||||
|
@ -10889,7 +10889,7 @@ skip_tx:
|
|||
test_tx, /* OUT cryptonote::transaction& tx, */
|
||||
test_ptx, /* OUT cryptonote::transaction& tx, */
|
||||
rct_config,
|
||||
loki_tx_params);
|
||||
tx_params);
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
tx.tx = test_tx;
|
||||
tx.ptx = test_ptx;
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||
#include "cryptonote_core/loki_name_system.h"
|
||||
#include "common/unordered_containers_boost_serialization.h"
|
||||
#include "common/util.h"
|
||||
#include "crypto/chacha.h"
|
||||
|
@ -80,6 +81,12 @@ class wallet_accessor_test;
|
|||
LOKI_RPC_DOC_INTROSPECT
|
||||
namespace tools
|
||||
{
|
||||
static const char *ERR_MSG_NETWORK_VERSION_QUERY_FAILED = tr("Could not query the current network version, try later");
|
||||
static const char *ERR_MSG_NETWORK_HEIGHT_QUERY_FAILED = tr("Could not query the current network block height, try later: ");
|
||||
static const char *ERR_MSG_SERVICE_NODE_LIST_QUERY_FAILED = tr("Failed to query daemon for service node list");
|
||||
static const char *ERR_MSG_TOO_MANY_TXS_CONSTRUCTED = tr("Constructed too many transations, please sweep_all first");
|
||||
static const char *ERR_MSG_EXCEPTION_THROWN = tr("Exception thrown, staking process could not be completed: ");
|
||||
|
||||
class ringdb;
|
||||
class wallet2;
|
||||
class Notify;
|
||||
|
@ -962,7 +969,7 @@ private:
|
|||
bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
|
||||
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
|
||||
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
|
||||
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, cryptonote::txtype tx_type = cryptonote::txtype::standard); // pass subaddr_indices by value on purpose
|
||||
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra_base, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, cryptonote::loki_construct_tx_params &tx_params);
|
||||
|
||||
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, cryptonote::txtype tx_type = cryptonote::txtype::standard);
|
||||
std::vector<wallet2::pending_tx> create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, cryptonote::txtype tx_type = cryptonote::txtype::standard);
|
||||
|
@ -1389,8 +1396,9 @@ private:
|
|||
uint64_t adjust_mixin(uint64_t mixin) const;
|
||||
uint32_t adjust_priority(uint32_t priority);
|
||||
|
||||
// params constructor, accumulates the burn amounts if the priority is a blink and, or a lns tx
|
||||
static cryptonote::loki_construct_tx_params construct_params(uint8_t hf_version, cryptonote::txtype tx_type, uint32_t priority);
|
||||
// params constructor, accumulates the burn amounts if the priority is
|
||||
// a blink and, or a lns tx. If it is a blink TX, lns_burn_type is ignored.
|
||||
static cryptonote::loki_construct_tx_params construct_params(uint8_t hf_version, cryptonote::txtype tx_type, uint32_t priority, lns::burn_type lns_burn_type = lns::burn_type::none);
|
||||
|
||||
bool is_unattended() const { return m_unattended; }
|
||||
|
||||
|
|
|
@ -863,7 +863,16 @@ namespace tools
|
|||
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
if (req.blink) priority = tools::tx_priority_blink;
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
|
||||
|
||||
boost::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
|
||||
if (!hf_version)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_HF_QUERY_FAILED;
|
||||
er.message = tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
|
||||
return false;
|
||||
}
|
||||
cryptonote::loki_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, cryptonote::txtype::standard, priority);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, tx_params);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
|
@ -916,8 +925,18 @@ namespace tools
|
|||
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
if (req.blink) priority = tools::tx_priority_blink;
|
||||
|
||||
boost::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
|
||||
if (!hf_version)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_HF_QUERY_FAILED;
|
||||
er.message = tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
cryptonote::loki_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, cryptonote::txtype::standard, priority);
|
||||
LOG_PRINT_L2("on_transfer_split calling create_transactions_2");
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, tx_params);
|
||||
LOG_PRINT_L2("on_transfer_split called create_transactions_2");
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay, req.blink,
|
||||
|
|
|
@ -2870,10 +2870,10 @@ namespace wallet_rpc
|
|||
{
|
||||
struct request_t
|
||||
{
|
||||
std::string type; // The mapping type, either "blockchain", "lokinet", "messenger" or if custom, a value between [65-65536] (0-2 map to the predefined mappings listed earlier).
|
||||
std::string type; // The mapping type, either "blockchain", "lokinet", "session" or if custom, a value between [65-65536] (0-2 map to the predefined mappings listed earlier).
|
||||
std::string owner; // (Optional): The owner of the mapping (wallet spend key as ed25519 public key in hex). For Lokinet, the owner has the ability to renew the Loki Name Service entry. By default/if field is empty, it is derived from the wallet purchasing the LNS mapping.
|
||||
std::string name; // The name to purchase via Loki Name Service
|
||||
std::string value; // The value that the name maps to via Loki Name Service, (i.e. For wallets: name -> wallet address. For messenger: display name -> messenger public key. For Lokinet: name -> domain name).
|
||||
std::string value; // The value that the name maps to via Loki Name Service, (i.e. For wallets: name -> wallet address. For session: display name -> session public key. For Lokinet: name -> domain name).
|
||||
|
||||
uint32_t account_index; // (Optional) Transfer from this account index. (Defaults to 0)
|
||||
std::set<uint32_t> subaddr_indices; // (Optional) Transfer from this set of subaddresses. (Defaults to 0)
|
||||
|
|
|
@ -78,3 +78,4 @@
|
|||
|
||||
// Loki:
|
||||
#define WALLET_RPC_ERROR_CODE_BLINK_FAILED -1000
|
||||
#define WALLET_RPC_ERROR_CODE_HF_QUERY_FAILED -1001
|
||||
|
|
|
@ -521,14 +521,13 @@ cryptonote::transaction loki_chain_generator::create_loki_name_system_tx(crypton
|
|||
cryptonote::block const &head = top().block;
|
||||
uint64_t new_height = get_block_height(top().block) + 1;
|
||||
uint8_t new_hf_version = get_hf_version_at(new_height);
|
||||
if (burn == LNS_AUTO_BURN) burn = lns::burn_requirement_in_atomic_loki(new_hf_version);
|
||||
if (burn == LNS_AUTO_BURN)
|
||||
burn = lns::burn_requirement_in_atomic_loki(new_hf_version,
|
||||
lns::mapping_type_to_burn_type(static_cast<lns::mapping_type>(type)));
|
||||
|
||||
crypto::hash prev_txid = crypto::null_hash;
|
||||
if (type == static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
{
|
||||
if (lns::mapping_record mapping = lns_db_.get_mapping(type, name))
|
||||
prev_txid = mapping.txid;
|
||||
}
|
||||
if (lns::mapping_record mapping = lns_db_.get_mapping(type, name))
|
||||
prev_txid = mapping.txid;
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
cryptonote::tx_extra_loki_name_system data(pkey, type, name, value, prev_txid);
|
||||
|
|
|
@ -126,6 +126,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(loki_name_system_disallow_reserved_type);
|
||||
GENERATE_AND_PLAY(loki_name_system_expiration);
|
||||
GENERATE_AND_PLAY(loki_name_system_get_mappings_by_user);
|
||||
GENERATE_AND_PLAY(loki_name_system_get_mapping_by_name_and_type);
|
||||
GENERATE_AND_PLAY(loki_name_system_handles_duplicate_in_lns_db);
|
||||
GENERATE_AND_PLAY(loki_name_system_handles_duplicate_in_tx_pool);
|
||||
GENERATE_AND_PLAY(loki_name_system_invalid_tx_extra_params);
|
||||
|
|
|
@ -1003,14 +1003,14 @@ bool loki_name_system_disallow_reserved_type::generate(std::vector<test_event_en
|
|||
gen.add_mined_money_unlock_blocks();
|
||||
|
||||
std::string mapping_value = "asdf";
|
||||
cryptonote::transaction tx1 = gen.create_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::start_reserved), mapping_value, "FriendlyName");
|
||||
cryptonote::transaction tx1 = gen.create_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::start_unusable_range), mapping_value, "FriendlyName");
|
||||
gen.add_tx(tx1, false /*can_be_added_to_blockchain*/, "Can't create a LNS TX that requests a LNS type that is unused but reserved by the protocol");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lns_mapping_type_enabled(lns::mapping_type type)
|
||||
{
|
||||
bool result = !(type >= lns::mapping_type::start_reserved && type <= lns::mapping_type::end_reserved);
|
||||
bool result = !(type >= lns::mapping_type::start_unusable_range && type <= lns::mapping_type::end_unusable_range);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1018,12 +1018,12 @@ struct lns_keys_t
|
|||
{
|
||||
crypto::ed25519_public_key ed_key;
|
||||
crypto::ed25519_secret_key ed_skey;
|
||||
std::string blockchain_value; // NOTE: this field is the binary (value) part of the name -> (value) mapping
|
||||
std::string wallet_value; // NOTE: this field is the binary (value) part of the name -> (value) mapping
|
||||
std::string lokinet_value;
|
||||
std::string messenger_value;
|
||||
std::string session_value;
|
||||
|
||||
std::string messenger_value_hex; // NOTE: likewise, but represented in hex, except, for blockchain, which is the cryptonote account address
|
||||
std::string blockchain_value_hex;
|
||||
std::string session_value_hex; // NOTE: likewise, but represented in hex, except, for blockchain, which is the cryptonote account address
|
||||
std::string wallet_value_hex;
|
||||
std::string lokinet_value_hex;
|
||||
};
|
||||
|
||||
|
@ -1032,16 +1032,16 @@ static lns_keys_t make_lns_keys(cryptonote::account_base const &src)
|
|||
lns_keys_t result = {};
|
||||
crypto_sign_ed25519_seed_keypair(result.ed_key.data, result.ed_skey.data, reinterpret_cast<const unsigned char *>(src.get_keys().m_spend_secret_key.data));
|
||||
|
||||
char messenger_value[lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH] = {};
|
||||
messenger_value[0] = 5; // prefix with 0x05
|
||||
memcpy(messenger_value + 1, &result.ed_key, sizeof(result.ed_key));
|
||||
char session_value[lns::SESSION_PUBLIC_KEY_BINARY_LENGTH] = {};
|
||||
session_value[0] = 5; // prefix with 0x05
|
||||
memcpy(session_value + 1, &result.ed_key, sizeof(result.ed_key));
|
||||
|
||||
result.messenger_value = std::string(messenger_value, sizeof(messenger_value));
|
||||
result.blockchain_value = std::string((char *)&src.get_keys().m_account_address, sizeof(src.get_keys().m_account_address));
|
||||
result.session_value = std::string(session_value, sizeof(session_value));
|
||||
result.wallet_value = std::string((char *)&src.get_keys().m_account_address, sizeof(src.get_keys().m_account_address));
|
||||
result.lokinet_value = std::string((char *)result.ed_key.data, sizeof(result.ed_key.data));
|
||||
|
||||
result.messenger_value_hex = epee::string_tools::pod_to_hex(messenger_value);
|
||||
result.blockchain_value_hex = cryptonote::get_account_address_as_str(cryptonote::FAKECHAIN, false /*subaddress*/, src.get_keys().m_account_address);
|
||||
result.session_value_hex = epee::string_tools::pod_to_hex(session_value);
|
||||
result.wallet_value_hex = cryptonote::get_account_address_as_str(cryptonote::FAKECHAIN, false /*subaddress*/, src.get_keys().m_account_address);
|
||||
result.lokinet_value_hex = epee::string_tools::pod_to_hex(result.ed_key);
|
||||
return result;
|
||||
}
|
||||
|
@ -1060,7 +1060,7 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
|
|||
lns_keys_t miner_key = make_lns_keys(miner);
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet))
|
||||
{
|
||||
char const name[] = "mydomain.loki";
|
||||
std::string const name = "mydomain.loki";
|
||||
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key.lokinet_value, name);
|
||||
gen.create_and_add_next_block({tx});
|
||||
|
||||
|
@ -1077,10 +1077,10 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
|
|||
CHECK_EQ(user.id, 1);
|
||||
CHECK_EQ(miner_key.ed_key, user.key);
|
||||
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name, loki::char_count(name));
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name);
|
||||
CHECK_EQ(mappings.loaded, true);
|
||||
CHECK_EQ(mappings.type, static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
CHECK_EQ(mappings.name, std::string(name));
|
||||
CHECK_EQ(mappings.name, name);
|
||||
CHECK_EQ(mappings.value, miner_key.lokinet_value);
|
||||
CHECK_EQ(mappings.register_height, height_of_lns_entry);
|
||||
CHECK_EQ(mappings.user_id, user.id);
|
||||
|
@ -1101,11 +1101,11 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
|
|||
CHECK_EQ(user.id, 1);
|
||||
CHECK_EQ(miner_key.ed_key, user.key);
|
||||
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name, loki::char_count(name));
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name);
|
||||
CHECK_EQ(mappings.loaded, true);
|
||||
CHECK_EQ(mappings.active(cryptonote::FAKECHAIN, blockchain_height), false);
|
||||
CHECK_EQ(mappings.type, static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
CHECK_EQ(mappings.name, std::string(name));
|
||||
CHECK_EQ(mappings.name, name);
|
||||
CHECK_EQ(mappings.value, miner_key.lokinet_value);
|
||||
CHECK_EQ(mappings.register_height, height_of_lns_entry);
|
||||
CHECK_EQ(mappings.user_id, user.id);
|
||||
|
@ -1135,14 +1135,14 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
|
|||
}
|
||||
|
||||
lns_keys_t bob_key = make_lns_keys(bob);
|
||||
std::string messenger_name1 = "MyName";
|
||||
std::string messenger_name2 = "AnotherName";
|
||||
std::string session_name1 = "MyName";
|
||||
std::string session_name2 = "AnotherName";
|
||||
{
|
||||
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name1);
|
||||
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name2, &bob_key.ed_key);
|
||||
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name1);
|
||||
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name2, &bob_key.ed_key);
|
||||
gen.create_and_add_next_block({tx1, tx2});
|
||||
}
|
||||
uint64_t messenger_height = gen.height();
|
||||
uint64_t session_height = gen.height();
|
||||
|
||||
// NOTE: Register some Lokinet names
|
||||
std::string lokinet_name1 = "lorem.loki";
|
||||
|
@ -1160,12 +1160,12 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
|
|||
// NOTE: Register some wallet names
|
||||
std::string wallet_name1 = "Wallet1";
|
||||
std::string wallet_name2 = "Wallet2";
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet))
|
||||
{
|
||||
{
|
||||
std::string bob_addr = cryptonote::get_account_address_as_str(cryptonote::FAKECHAIN, false, bob.get_keys().m_account_address);
|
||||
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::blockchain), bob_key.blockchain_value, wallet_name1);
|
||||
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::blockchain), bob_key.blockchain_value, wallet_name2, &bob_key.ed_key);
|
||||
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::wallet), bob_key.wallet_value, wallet_name1);
|
||||
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::wallet), bob_key.wallet_value, wallet_name2, &bob_key.ed_key);
|
||||
gen.create_and_add_next_block({tx1, tx2});
|
||||
}
|
||||
}
|
||||
|
@ -1173,7 +1173,7 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
|
|||
|
||||
loki_register_callback(events, "check_lns_entries", [&events, bob_key,
|
||||
wallet_height, wallet_name1, wallet_name2,
|
||||
messenger_height, messenger_name1, messenger_name2,
|
||||
session_height, session_name1, session_name2,
|
||||
lokinet_height, lokinet_name1, lokinet_name2
|
||||
](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
|
@ -1182,21 +1182,21 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
|
|||
std::vector<lns::mapping_record> records = lns_db.get_mappings_by_user(bob_key.ed_key);
|
||||
|
||||
size_t expected_size = 0;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::messenger)) expected_size += 2;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain)) expected_size += 2;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::session)) expected_size += 2;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet)) expected_size += 2;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet)) expected_size += 2;
|
||||
CHECK_EQ(records.size(), expected_size);
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::messenger))
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::session))
|
||||
{
|
||||
CHECK_EQ(records[0].name, messenger_name1);
|
||||
CHECK_EQ(records[1].name, messenger_name2);
|
||||
CHECK_EQ(records[0].register_height, messenger_height);
|
||||
CHECK_EQ(records[1].register_height, messenger_height);
|
||||
CHECK_EQ(records[0].value, bob_key.messenger_value);
|
||||
CHECK_EQ(records[1].value, bob_key.messenger_value);
|
||||
CHECK_EQ(records[0].type, static_cast<uint16_t>(lns::mapping_type::messenger));
|
||||
CHECK_EQ(records[1].type, static_cast<uint16_t>(lns::mapping_type::messenger));
|
||||
CHECK_EQ(records[0].name, session_name1);
|
||||
CHECK_EQ(records[1].name, session_name2);
|
||||
CHECK_EQ(records[0].register_height, session_height);
|
||||
CHECK_EQ(records[1].register_height, session_height);
|
||||
CHECK_EQ(records[0].value, bob_key.session_value);
|
||||
CHECK_EQ(records[1].value, bob_key.session_value);
|
||||
CHECK_EQ(records[0].type, static_cast<uint16_t>(lns::mapping_type::session));
|
||||
CHECK_EQ(records[1].type, static_cast<uint16_t>(lns::mapping_type::session));
|
||||
}
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet))
|
||||
|
@ -1211,16 +1211,16 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
|
|||
CHECK_EQ(records[3].type, static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
}
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet))
|
||||
{
|
||||
CHECK_EQ(records[4].name, wallet_name1);
|
||||
CHECK_EQ(records[5].name, wallet_name2);
|
||||
CHECK_EQ(records[4].register_height, wallet_height);
|
||||
CHECK_EQ(records[5].register_height, wallet_height);
|
||||
CHECK_EQ(records[4].value, bob_key.blockchain_value);
|
||||
CHECK_EQ(records[5].value, bob_key.blockchain_value);
|
||||
CHECK_EQ(records[4].type, static_cast<uint16_t>(lns::mapping_type::blockchain));
|
||||
CHECK_EQ(records[5].type, static_cast<uint16_t>(lns::mapping_type::blockchain));
|
||||
CHECK_EQ(records[4].value, bob_key.wallet_value);
|
||||
CHECK_EQ(records[5].value, bob_key.wallet_value);
|
||||
CHECK_EQ(records[4].type, static_cast<uint16_t>(lns::mapping_type::wallet));
|
||||
CHECK_EQ(records[5].type, static_cast<uint16_t>(lns::mapping_type::wallet));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
@ -1228,6 +1228,53 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
|
|||
return true;
|
||||
}
|
||||
|
||||
bool loki_name_system_get_mapping_by_name_and_type::generate(std::vector<test_event_entry> &events)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
|
||||
loki_chain_generator gen(events, hard_forks);
|
||||
|
||||
cryptonote::account_base miner = gen.first_miner_;
|
||||
cryptonote::account_base bob = gen.add_account();
|
||||
gen.add_blocks_until_version(hard_forks.back().first);
|
||||
|
||||
// NOTE: Fund Bob's wallet
|
||||
{
|
||||
gen.add_n_blocks(10); /// generate some outputs and unlock them
|
||||
gen.add_mined_money_unlock_blocks();
|
||||
|
||||
cryptonote::transaction transfer = gen.create_and_add_tx(miner, bob.get_keys().m_account_address, MK_COINS(400));
|
||||
gen.create_and_add_next_block({transfer});
|
||||
gen.add_mined_money_unlock_blocks();
|
||||
}
|
||||
|
||||
lns_keys_t bob_key = make_lns_keys(bob);
|
||||
std::string session_name1 = "MyName";
|
||||
crypto::hash session_tx_hash;
|
||||
{
|
||||
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name1);
|
||||
session_tx_hash = cryptonote::get_transaction_hash(tx1);
|
||||
gen.create_and_add_next_block({tx1});
|
||||
}
|
||||
uint64_t session_height = gen.height();
|
||||
|
||||
loki_register_callback(events, "check_lns_entries", [&events, bob_key, session_height, session_name1, session_tx_hash](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
DEFINE_TESTS_ERROR_CONTEXT("check_lns_entries");
|
||||
lns::name_system_db const &lns_db = c.get_blockchain_storage().name_system_db();
|
||||
lns::mapping_and_user_record record = lns_db.get_mapping_by_name_and_type(lns::mapping_type::session, session_name1);
|
||||
CHECK_EQ(record.mapping.type, static_cast<uint16_t>(lns::mapping_type::session));
|
||||
CHECK_EQ(record.mapping.name, session_name1);
|
||||
CHECK_EQ(record.mapping.value, bob_key.session_value);
|
||||
CHECK_EQ(record.mapping.register_height, session_height);
|
||||
CHECK_EQ(record.mapping.prev_txid, crypto::null_hash);
|
||||
CHECK_EQ(record.mapping.txid, session_tx_hash);
|
||||
CHECK_EQ(record.owner, bob_key.ed_key);
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_event_entry> &events)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
|
||||
|
@ -1246,16 +1293,16 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
|
|||
|
||||
lns_keys_t miner_key = make_lns_keys(miner);
|
||||
lns_keys_t bob_key = make_lns_keys(bob);
|
||||
std::string messenger_name = "myfriendlydisplayname.loki";
|
||||
std::string session_name = "myfriendlydisplayname.loki";
|
||||
uint16_t custom_type = 3928;
|
||||
{
|
||||
// NOTE: Allow duplicates with the same name but different type
|
||||
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
|
||||
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.messenger_value, messenger_name);
|
||||
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name);
|
||||
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.session_value, session_name);
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet))
|
||||
{
|
||||
cryptonote::transaction bar3 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key.lokinet_value, messenger_name);
|
||||
cryptonote::transaction bar3 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key.lokinet_value, session_name);
|
||||
gen.create_and_add_next_block({bar, bar2, bar3});
|
||||
}
|
||||
else
|
||||
|
@ -1266,11 +1313,11 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
|
|||
uint64_t height_of_lns_entry = gen.height();
|
||||
|
||||
{
|
||||
cryptonote::transaction bar6 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
|
||||
cryptonote::transaction bar6 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name);
|
||||
gen.add_tx(bar6, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in lns db");
|
||||
}
|
||||
|
||||
loki_register_callback(events, "check_lns_entries", [&events, height_of_lns_entry, miner_key, bob_key, messenger_name, custom_type](cryptonote::core &c, size_t ev_index)
|
||||
loki_register_callback(events, "check_lns_entries", [&events, height_of_lns_entry, miner_key, bob_key, session_name, custom_type](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
DEFINE_TESTS_ERROR_CONTEXT("check_lns_entries");
|
||||
lns::name_system_db const &lns_db = c.get_blockchain_storage().name_system_db();
|
||||
|
@ -1280,30 +1327,30 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
|
|||
CHECK_EQ(user.id, 1);
|
||||
CHECK_EQ(miner_key.ed_key, user.key);
|
||||
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::messenger), messenger_name);
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::session), session_name);
|
||||
CHECK_EQ(mappings.loaded, true);
|
||||
CHECK_EQ(mappings.type, static_cast<uint16_t>(lns::mapping_type::messenger));
|
||||
CHECK_EQ(mappings.name, messenger_name);
|
||||
CHECK_EQ(mappings.value, bob_key.messenger_value);
|
||||
CHECK_EQ(mappings.type, static_cast<uint16_t>(lns::mapping_type::session));
|
||||
CHECK_EQ(mappings.name, session_name);
|
||||
CHECK_EQ(mappings.value, bob_key.session_value);
|
||||
CHECK_EQ(mappings.register_height, height_of_lns_entry);
|
||||
CHECK_EQ(mappings.user_id, user.id);
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet))
|
||||
{
|
||||
lns::mapping_record mappings2 = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), messenger_name);
|
||||
lns::mapping_record mappings2 = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), session_name);
|
||||
CHECK_EQ(mappings2.loaded, true);
|
||||
CHECK_EQ(mappings2.type, static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
CHECK_EQ(mappings2.name, messenger_name);
|
||||
CHECK_EQ(mappings2.name, session_name);
|
||||
CHECK_EQ(mappings2.value, miner_key.lokinet_value);
|
||||
CHECK_EQ(mappings2.register_height, height_of_lns_entry);
|
||||
CHECK_EQ(mappings2.user_id, user.id);
|
||||
}
|
||||
|
||||
lns::mapping_record mappings3 = lns_db.get_mapping(custom_type, messenger_name);
|
||||
lns::mapping_record mappings3 = lns_db.get_mapping(custom_type, session_name);
|
||||
CHECK_EQ(mappings3.loaded, true);
|
||||
CHECK_EQ(mappings3.type, custom_type);
|
||||
CHECK_EQ(mappings3.name, messenger_name);
|
||||
CHECK_EQ(mappings3.value, bob_key.messenger_value);
|
||||
CHECK_EQ(mappings3.name, session_name);
|
||||
CHECK_EQ(mappings3.value, bob_key.session_value);
|
||||
CHECK_EQ(mappings3.register_height, height_of_lns_entry);
|
||||
CHECK_EQ(mappings3.user_id, user.id);
|
||||
|
||||
|
@ -1333,16 +1380,16 @@ bool loki_name_system_handles_duplicate_in_tx_pool::generate(std::vector<test_ev
|
|||
|
||||
lns_keys_t miner_key = make_lns_keys(miner);
|
||||
lns_keys_t bob_key = make_lns_keys(bob);
|
||||
std::string messenger_name = "myfriendlydisplayname.loki";
|
||||
std::string session_name = "myfriendlydisplayname.loki";
|
||||
|
||||
uint16_t custom_type = 3928;
|
||||
{
|
||||
// NOTE: Allow duplicates with the same name but different type
|
||||
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
|
||||
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.messenger_value, messenger_name);
|
||||
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name);
|
||||
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.session_value, session_name);
|
||||
|
||||
// NOTE: Make duplicate in the TX pool, this should be rejected
|
||||
cryptonote::transaction bar4 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
|
||||
cryptonote::transaction bar4 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, session_name);
|
||||
gen.add_tx(bar4, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in tx pool");
|
||||
}
|
||||
return true;
|
||||
|
@ -1369,7 +1416,9 @@ bool loki_name_system_invalid_tx_extra_params::generate(std::vector<test_event_e
|
|||
char const *reason) -> void {
|
||||
uint64_t new_height = cryptonote::get_block_height(gen.top().block) + 1;
|
||||
uint8_t new_hf_version = gen.get_hf_version_at(new_height);
|
||||
uint64_t burn_requirement = lns::burn_requirement_in_atomic_loki(new_hf_version);
|
||||
|
||||
lns::burn_type burn_type = lns::mapping_type_to_burn_type(static_cast<lns::mapping_type>(data.type));
|
||||
uint64_t burn_requirement = lns::burn_requirement_in_atomic_loki(new_hf_version, burn_type);
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
cryptonote::add_loki_name_system_to_tx_extra(extra, data);
|
||||
|
@ -1387,16 +1436,16 @@ bool loki_name_system_invalid_tx_extra_params::generate(std::vector<test_event_e
|
|||
|
||||
cryptonote::tx_extra_loki_name_system valid_data = {};
|
||||
valid_data.owner = miner_key.ed_key;
|
||||
valid_data.type = static_cast<uint16_t>(lns::mapping_type::blockchain);
|
||||
valid_data.value = miner_key.blockchain_value;
|
||||
valid_data.type = static_cast<uint16_t>(lns::mapping_type::wallet);
|
||||
valid_data.value = miner_key.wallet_value;
|
||||
valid_data.name = "my_lns_name";
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet))
|
||||
{
|
||||
// Blockchain name too long
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
data.name = std::string(lns::BLOCKCHAIN_NAME_MAX + 1, 'A');
|
||||
data.name = std::string(lns::WALLET_NAME_MAX + 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Blockchain) Wallet to name in LNS too long");
|
||||
}
|
||||
|
||||
|
@ -1455,54 +1504,54 @@ bool loki_name_system_invalid_tx_extra_params::generate(std::vector<test_event_e
|
|||
}
|
||||
}
|
||||
|
||||
// Messenger value invalid, messenger keys require a 33 byte key where the first byte is a 0x05
|
||||
// Session value invalid, session keys require a 33 byte key where the first byte is a 0x05
|
||||
std::stringstream stream;
|
||||
valid_data.type = static_cast<uint16_t>(lns::mapping_type::messenger);
|
||||
valid_data.type = static_cast<uint16_t>(lns::mapping_type::session);
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
data.value[0] = 'a';
|
||||
stream << "(Messenger) Key invalid, not prefixed with 0x05";
|
||||
stream << "(Session) Key invalid, not prefixed with 0x05";
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, stream.str().c_str());
|
||||
stream.clear();
|
||||
}
|
||||
|
||||
// Messenger should be valid with this key with a 0x05 prefix
|
||||
valid_data.value = miner_key.messenger_value;
|
||||
// Session should be valid with this key with a 0x05 prefix
|
||||
valid_data.value = miner_key.session_value;
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
stream << "(Messenger) Key should be valid, prefixed with 0x05: " << miner_key.messenger_value_hex;
|
||||
stream << "(Session) Key should be valid, prefixed with 0x05: " << miner_key.session_value_hex;
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, true, stream.str().c_str());
|
||||
stream.clear();
|
||||
}
|
||||
|
||||
// Messenger value too short
|
||||
// We added valid tx prior, we should update name to avoid conflict names in messenger land and test other invalid params
|
||||
// Session value too short
|
||||
// We added valid tx prior, we should update name to avoid conflict names in session land and test other invalid params
|
||||
valid_data.name = "new_friendly_name";
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
data.value = std::string(lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH * 2 - 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Messenger) User id, value too short");
|
||||
data.value = std::string(lns::SESSION_PUBLIC_KEY_BINARY_LENGTH * 2 - 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Session) User id, value too short");
|
||||
}
|
||||
|
||||
// Messenger value too long
|
||||
// Session value too long
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
data.value = std::string(lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH * 2 + 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Messenger) User id, value too long");
|
||||
data.value = std::string(lns::SESSION_PUBLIC_KEY_BINARY_LENGTH * 2 + 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Session) User id, value too long");
|
||||
}
|
||||
|
||||
// Messenger name too long
|
||||
// Session name too long
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
data.name = std::string(lns::MESSENGER_DISPLAY_NAME_MAX + 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Messenger) User id, name too long");
|
||||
data.name = std::string(lns::SESSION_DISPLAY_NAME_MAX + 1, 'A');
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Session) User id, name too long");
|
||||
}
|
||||
|
||||
// Messenger name empty
|
||||
// Session name empty
|
||||
{
|
||||
cryptonote::tx_extra_loki_name_system data = valid_data;
|
||||
data.name = {};
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Messenger) User id, name too long");
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data, false, "(Session) User id, name too long");
|
||||
}
|
||||
|
||||
// Generic name empty
|
||||
|
@ -1564,17 +1613,17 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
uint64_t miner_earliest_renewable_height = 0;
|
||||
std::string const miner_lokinet_domain1 = "website.loki";
|
||||
std::string const miner_wallet_name1 = "MyWallet";
|
||||
std::string const miner_messenger_name1 = "I Like Loki";
|
||||
std::string const miner_session_name1 = "I Like Loki";
|
||||
{
|
||||
// NOTE: Generate and add the (transactions + block) to the blockchain
|
||||
{
|
||||
std::vector<cryptonote::transaction> txs;
|
||||
cryptonote::transaction messenger_tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::messenger), miner_key.messenger_value, miner_messenger_name1);
|
||||
txs.push_back(messenger_tx);
|
||||
cryptonote::transaction session_tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::session), miner_key.session_value, miner_session_name1);
|
||||
txs.push_back(session_tx);
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet))
|
||||
{
|
||||
cryptonote::transaction wallet_tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::blockchain), miner_key.blockchain_value, miner_wallet_name1);
|
||||
cryptonote::transaction wallet_tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::wallet), miner_key.wallet_value, miner_wallet_name1);
|
||||
txs.push_back(wallet_tx);
|
||||
}
|
||||
|
||||
|
@ -1595,24 +1644,24 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
miner_earliest_renewable_height = first_lns_height + expiry_blocks - renew_window;
|
||||
}
|
||||
|
||||
loki_register_callback(events, "check_first_lns_entries", [miner_key, miner_messenger_name1, miner_lokinet_domain1, miner_wallet_name1, first_lns_height](cryptonote::core &c, size_t ev_index)
|
||||
loki_register_callback(events, "check_first_lns_entries", [miner_key, miner_session_name1, miner_lokinet_domain1, miner_wallet_name1, first_lns_height](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
DEFINE_TESTS_ERROR_CONTEXT("check_first_lns_entries");
|
||||
lns::name_system_db const &lns_db = c.get_blockchain_storage().name_system_db();
|
||||
std::vector<lns::mapping_record> records = lns_db.get_mappings_by_user(miner_key.ed_key);
|
||||
|
||||
size_t expected_size = 1;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain)) expected_size += 1;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet)) expected_size += 1;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet)) expected_size += 1;
|
||||
CHECK_EQ(records.size(), expected_size);
|
||||
|
||||
for (lns::mapping_record const &record : records)
|
||||
{
|
||||
if (record.type == static_cast<uint16_t>(lns::mapping_type::messenger))
|
||||
if (record.type == static_cast<uint16_t>(lns::mapping_type::session))
|
||||
{
|
||||
CHECK_EQ(record.name, miner_messenger_name1);
|
||||
CHECK_EQ(record.name, miner_session_name1);
|
||||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.messenger_value);
|
||||
CHECK_EQ(record.value, miner_key.session_value);
|
||||
}
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
{
|
||||
|
@ -1620,11 +1669,11 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.lokinet_value);
|
||||
}
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::blockchain))
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::wallet))
|
||||
{
|
||||
CHECK_EQ(record.name, miner_wallet_name1);
|
||||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.blockchain_value);
|
||||
CHECK_EQ(record.value, miner_key.wallet_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1638,13 +1687,13 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
while (gen.height() <= miner_earliest_renewable_height)
|
||||
gen.create_and_add_next_block();
|
||||
|
||||
// NOTE: Generate and add the second round of (transactions + block) to the blockchain, renew lokinet and add bob's messenger
|
||||
// NOTE: Generate and add the second round of (transactions + block) to the blockchain, renew lokinet and add bob's session
|
||||
uint64_t second_lns_height = 0;
|
||||
{
|
||||
std::string const bob_messenger_name1 = "I Like Session";
|
||||
std::string const bob_session_name1 = "I Like Session";
|
||||
{
|
||||
std::vector<cryptonote::transaction> txs;
|
||||
txs.push_back(gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, bob_messenger_name1));
|
||||
txs.push_back(gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::session), bob_key.session_value, bob_session_name1));
|
||||
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet))
|
||||
{
|
||||
|
@ -1654,8 +1703,8 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
}
|
||||
second_lns_height = gen.height();
|
||||
|
||||
loki_register_callback(events, "check_second_lns_entries", [miner_lokinet_domain1, bob_messenger_name1, second_lns_height, miner_key, bob_key,
|
||||
first_lns_height, miner_messenger_name1, miner_wallet_name1](cryptonote::core &c, size_t ev_index)
|
||||
loki_register_callback(events, "check_second_lns_entries", [miner_lokinet_domain1, bob_session_name1, second_lns_height, miner_key, bob_key,
|
||||
first_lns_height, miner_session_name1, miner_wallet_name1](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
DEFINE_TESTS_ERROR_CONTEXT("check_second_lns_entries");
|
||||
lns::name_system_db const &lns_db = c.get_blockchain_storage().name_system_db();
|
||||
|
@ -1666,11 +1715,11 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
std::vector<lns::mapping_record> records = lns_db.get_mappings_by_user(miner_key.ed_key);
|
||||
for (lns::mapping_record const &record : records)
|
||||
{
|
||||
if (record.type == static_cast<uint16_t>(lns::mapping_type::messenger))
|
||||
if (record.type == static_cast<uint16_t>(lns::mapping_type::session))
|
||||
{
|
||||
CHECK_EQ(record.name, miner_messenger_name1);
|
||||
CHECK_EQ(record.name, miner_session_name1);
|
||||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.messenger_value);
|
||||
CHECK_EQ(record.value, miner_key.session_value);
|
||||
}
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
{
|
||||
|
@ -1678,11 +1727,11 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
CHECK_EQ(record.register_height, second_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.lokinet_value);
|
||||
}
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::blockchain))
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::wallet))
|
||||
{
|
||||
CHECK_EQ(record.name, miner_wallet_name1);
|
||||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.blockchain_value);
|
||||
CHECK_EQ(record.value, miner_key.wallet_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1695,17 +1744,17 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
{
|
||||
std::vector<lns::mapping_record> records = lns_db.get_mappings_by_user(bob_key.ed_key);
|
||||
CHECK_EQ(records.size(), 1);
|
||||
CHECK_EQ(records[0].name, bob_messenger_name1);
|
||||
CHECK_EQ(records[0].name, bob_session_name1);
|
||||
CHECK_EQ(records[0].register_height, second_lns_height);
|
||||
CHECK_EQ(records[0].value, bob_key.messenger_value);
|
||||
CHECK_EQ(records[0].type, static_cast<uint16_t>(lns::mapping_type::messenger));
|
||||
CHECK_EQ(records[0].value, bob_key.session_value);
|
||||
CHECK_EQ(records[0].type, static_cast<uint16_t>(lns::mapping_type::session));
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
loki_register_callback(events, "trigger_blockchain_detach", [miner_key, miner_messenger_name1, miner_lokinet_domain1, miner_wallet_name1, first_lns_height, second_lns_height, bob_key](cryptonote::core &c, size_t ev_index)
|
||||
loki_register_callback(events, "trigger_blockchain_detach", [miner_key, miner_session_name1, miner_lokinet_domain1, miner_wallet_name1, first_lns_height, second_lns_height, bob_key](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
DEFINE_TESTS_ERROR_CONTEXT("check_second_lns_entries");
|
||||
cryptonote::Blockchain &blockchain = c.get_blockchain_storage();
|
||||
|
@ -1729,17 +1778,17 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
{
|
||||
std::vector<lns::mapping_record> records = lns_db.get_mappings_by_user(miner_key.ed_key);
|
||||
size_t expected_size = 1;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain)) expected_size += 1;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet)) expected_size += 1;
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::lokinet)) expected_size += 1;
|
||||
CHECK_EQ(records.size(), expected_size);
|
||||
|
||||
for (lns::mapping_record const &record : records)
|
||||
{
|
||||
if (record.type == static_cast<uint16_t>(lns::mapping_type::messenger))
|
||||
if (record.type == static_cast<uint16_t>(lns::mapping_type::session))
|
||||
{
|
||||
CHECK_EQ(record.name, miner_messenger_name1);
|
||||
CHECK_EQ(record.name, miner_session_name1);
|
||||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.messenger_value);
|
||||
CHECK_EQ(record.value, miner_key.session_value);
|
||||
}
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::lokinet))
|
||||
{
|
||||
|
@ -1747,11 +1796,11 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
|
|||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.lokinet_value);
|
||||
}
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::blockchain))
|
||||
else if (record.type == static_cast<uint16_t>(lns::mapping_type::wallet))
|
||||
{
|
||||
CHECK_EQ(record.name, miner_wallet_name1);
|
||||
CHECK_EQ(record.register_height, first_lns_height);
|
||||
CHECK_EQ(record.value, miner_key.blockchain_value);
|
||||
CHECK_EQ(record.value, miner_key.wallet_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1803,7 +1852,7 @@ bool loki_name_system_name_renewal::generate(std::vector<test_event_entry> &even
|
|||
}
|
||||
|
||||
lns_keys_t miner_key = make_lns_keys(miner);
|
||||
char const name[] = "mydomain.loki";
|
||||
std::string const name = "mydomain.loki";
|
||||
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key.lokinet_value, name);
|
||||
gen.create_and_add_next_block({tx});
|
||||
crypto::hash prev_txid = get_transaction_hash(tx);
|
||||
|
@ -1823,10 +1872,10 @@ bool loki_name_system_name_renewal::generate(std::vector<test_event_entry> &even
|
|||
CHECK_EQ(user.id, 1);
|
||||
CHECK_EQ(miner_key.ed_key, user.key);
|
||||
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name, loki::char_count(name));
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name);
|
||||
CHECK_EQ(mappings.loaded, true);
|
||||
CHECK_EQ(mappings.type, static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
CHECK_EQ(mappings.name, std::string(name));
|
||||
CHECK_EQ(mappings.name, name);
|
||||
CHECK_EQ(mappings.value, miner_key.lokinet_value);
|
||||
CHECK_EQ(mappings.register_height, height_of_lns_entry);
|
||||
CHECK_EQ(mappings.prev_txid, crypto::null_hash);
|
||||
|
@ -1852,10 +1901,10 @@ bool loki_name_system_name_renewal::generate(std::vector<test_event_entry> &even
|
|||
CHECK_EQ(user.id, 1);
|
||||
CHECK_EQ(miner_key.ed_key, user.key);
|
||||
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name, loki::char_count(name));
|
||||
lns::mapping_record mappings = lns_db.get_mapping(static_cast<uint16_t>(lns::mapping_type::lokinet), name);
|
||||
CHECK_EQ(mappings.loaded, true);
|
||||
CHECK_EQ(mappings.type, static_cast<uint16_t>(lns::mapping_type::lokinet));
|
||||
CHECK_EQ(mappings.name, std::string(name));
|
||||
CHECK_EQ(mappings.name, name);
|
||||
CHECK_EQ(mappings.value, miner_key.lokinet_value);
|
||||
CHECK_EQ(mappings.register_height, renewal_height);
|
||||
CHECK_EQ(mappings.prev_txid, prev_txid);
|
||||
|
@ -1879,12 +1928,13 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
|
|||
auto make_lns_tx_with_custom_extra = [&](loki_chain_generator &gen,
|
||||
std::vector<test_event_entry> &events,
|
||||
cryptonote::account_base const &src,
|
||||
cryptonote::tx_extra_loki_name_system &data) -> void {
|
||||
cryptonote::tx_extra_loki_name_system const &data) -> void {
|
||||
|
||||
uint64_t new_height = cryptonote::get_block_height(gen.top().block) + 1;
|
||||
uint8_t new_hf_version = gen.get_hf_version_at(new_height);
|
||||
|
||||
uint64_t burn_requirement = lns::burn_requirement_in_atomic_loki(new_hf_version);
|
||||
lns::burn_type burn_type = lns::mapping_type_to_burn_type(static_cast<lns::mapping_type>(data.type));
|
||||
uint64_t burn_requirement = lns::burn_requirement_in_atomic_loki(new_hf_version, burn_type);
|
||||
std::vector<uint8_t> extra;
|
||||
cryptonote::add_loki_name_system_to_tx_extra(extra, data);
|
||||
cryptonote::add_burned_amount_to_tx_extra(extra, burn_requirement);
|
||||
|
@ -1904,11 +1954,11 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
|
|||
data.owner = miner_key.ed_key;
|
||||
|
||||
// Blockchain
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
|
||||
if (lns_mapping_type_enabled(lns::mapping_type::wallet))
|
||||
{
|
||||
data.type = static_cast<uint16_t>(lns::mapping_type::blockchain);
|
||||
data.name = std::string(lns::BLOCKCHAIN_NAME_MAX, 'A');
|
||||
data.value = miner_key.blockchain_value;
|
||||
data.type = static_cast<uint16_t>(lns::mapping_type::wallet);
|
||||
data.name = std::string(lns::WALLET_NAME_MAX, 'A');
|
||||
data.value = miner_key.wallet_value;
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data);
|
||||
}
|
||||
|
||||
|
@ -1921,11 +1971,11 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
|
|||
make_lns_tx_with_custom_extra(gen, events, miner, data);
|
||||
}
|
||||
|
||||
// Messenger
|
||||
// Session
|
||||
{
|
||||
data.type = static_cast<uint16_t>(lns::mapping_type::messenger);
|
||||
data.name = std::string(lns::MESSENGER_DISPLAY_NAME_MAX, 'A');
|
||||
data.value = std::string(lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH, 'a');
|
||||
data.type = static_cast<uint16_t>(lns::mapping_type::session);
|
||||
data.name = std::string(lns::SESSION_DISPLAY_NAME_MAX, 'A');
|
||||
data.value = std::string(lns::SESSION_PUBLIC_KEY_BINARY_LENGTH, 'a');
|
||||
data.value[0] = '0';
|
||||
data.value[1] = '5';
|
||||
make_lns_tx_with_custom_extra(gen, events, miner, data);
|
||||
|
@ -1956,7 +2006,7 @@ bool loki_name_system_wrong_burn::generate(std::vector<test_event_entry> &events
|
|||
}
|
||||
|
||||
lns_keys_t lns_keys = make_lns_keys(miner);
|
||||
lns::mapping_type const types[] = {lns::mapping_type::messenger, lns::mapping_type::blockchain, lns::mapping_type::lokinet};
|
||||
lns::mapping_type const types[] = {lns::mapping_type::session, lns::mapping_type::wallet, lns::mapping_type::lokinet};
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
bool under_burn = (i == 0);
|
||||
|
@ -1967,14 +2017,14 @@ bool loki_name_system_wrong_burn::generate(std::vector<test_event_entry> &events
|
|||
std::string value;
|
||||
std::string name;
|
||||
|
||||
if (type == lns::mapping_type::messenger)
|
||||
if (type == lns::mapping_type::session)
|
||||
{
|
||||
value = lns_keys.messenger_value;
|
||||
name = "My Friendly Messenger Name";
|
||||
value = lns_keys.session_value;
|
||||
name = "My Friendly Session Name";
|
||||
}
|
||||
else if (type == lns::mapping_type::blockchain)
|
||||
else if (type == lns::mapping_type::wallet)
|
||||
{
|
||||
value = lns_keys.blockchain_value;
|
||||
value = lns_keys.wallet_value;
|
||||
name = "My Friendly Wallet Name";
|
||||
}
|
||||
else if (type == lns::mapping_type::lokinet)
|
||||
|
@ -1985,9 +2035,10 @@ bool loki_name_system_wrong_burn::generate(std::vector<test_event_entry> &events
|
|||
else
|
||||
assert("Unhandled type enum" == nullptr);
|
||||
|
||||
uint64_t new_height = cryptonote::get_block_height(gen.top().block) + 1;
|
||||
uint8_t new_hf_version = gen.get_hf_version_at(new_height);
|
||||
uint64_t burn = lns::burn_requirement_in_atomic_loki(new_hf_version);
|
||||
uint64_t new_height = cryptonote::get_block_height(gen.top().block) + 1;
|
||||
uint8_t new_hf_version = gen.get_hf_version_at(new_height);
|
||||
lns::burn_type burn_type = lns::mapping_type_to_burn_type(type);
|
||||
uint64_t burn = lns::burn_requirement_in_atomic_loki(new_hf_version, burn_type);
|
||||
if (under_burn) burn -= 1;
|
||||
else burn += 1;
|
||||
|
||||
|
@ -2013,13 +2064,13 @@ bool loki_name_system_wrong_version::generate(std::vector<test_event_entry> &eve
|
|||
cryptonote::tx_extra_loki_name_system data = {};
|
||||
data.version = 0xFF;
|
||||
data.owner = miner_key.ed_key;
|
||||
data.type = static_cast<uint16_t>(lns::mapping_type::messenger);
|
||||
data.value = miner_key.messenger_value;
|
||||
data.type = static_cast<uint16_t>(lns::mapping_type::session);
|
||||
data.value = miner_key.session_value;
|
||||
data.name = "my_lns_name";
|
||||
|
||||
uint64_t new_height = cryptonote::get_block_height(gen.top().block) + 1;
|
||||
uint8_t new_hf_version = gen.get_hf_version_at(new_height);
|
||||
uint64_t burn_requirement = lns::burn_requirement_in_atomic_loki(new_hf_version);
|
||||
uint64_t burn_requirement = lns::burn_requirement_in_atomic_loki(new_hf_version, lns::burn_type::session);
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
cryptonote::add_loki_name_system_to_tx_extra(extra, data);
|
||||
|
|
|
@ -54,6 +54,7 @@ struct loki_core_test_state_change_ip_penalty_disallow_dupes
|
|||
struct loki_name_system_disallow_reserved_type : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_expiration : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_get_mappings_by_user : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_get_mapping_by_name_and_type : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_handles_duplicate_in_lns_db : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_handles_duplicate_in_tx_pool : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_invalid_tx_extra_params : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
|
|
|
@ -86,7 +86,15 @@ bool do_send_money(tools::wallet2& w1, tools::wallet2& w2, size_t mix_in_factor,
|
|||
try
|
||||
{
|
||||
std::vector<tools::wallet2::pending_tx> ptx;
|
||||
ptx = w1.create_transactions_2(dsts, mix_in_factor, 0, 0, std::vector<uint8_t>(), 0, {}, {});
|
||||
cryptonote::loki_construct_tx_params tx_params;
|
||||
ptx = w1.create_transactions_2(dsts,
|
||||
mix_in_factor,
|
||||
0 /*unlock_time*/,
|
||||
0 /*priority*/,
|
||||
std::vector<uint8_t>() /*extra_base*/,
|
||||
0 /*subaddr_account*/,
|
||||
{} /*subaddr_indices*/,
|
||||
tx_params);
|
||||
for (auto &p: ptx)
|
||||
w1.commit_tx(p);
|
||||
return true;
|
||||
|
|
|
@ -12,53 +12,53 @@ TEST(loki_name_system, lokinet_domain_names)
|
|||
|
||||
// Should work
|
||||
{
|
||||
char const name[] = "mydomain.loki";
|
||||
ASSERT_TRUE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "mydomain.loki";
|
||||
ASSERT_TRUE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "a.loki";
|
||||
ASSERT_TRUE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "a.loki";
|
||||
ASSERT_TRUE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "xn--bcher-kva.loki";
|
||||
ASSERT_TRUE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "xn--bcher-kva.loki";
|
||||
ASSERT_TRUE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
// Should fail
|
||||
{
|
||||
char const name[] = "";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "mydomain.loki.example";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "mydomain.loki.example";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "mydomain.loki.com";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "mydomain.loki.com";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "mydomain.com";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "mydomain.com";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "mydomain";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "mydomain";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "xn--bcher-kva.lok";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "xn--bcher-kva.lok";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
|
||||
{
|
||||
char const name[] = "a_b_c.loki";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
|
||||
std::string const name = "a_b_c.loki";
|
||||
ASSERT_FALSE(lns::validate_lns_name(lokinet, name));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue