Send LNS values as blobs to the blockchain

This commit is contained in:
Doyle 2020-01-24 17:48:52 +11:00
parent cb955c1952
commit 1093bab034
8 changed files with 364 additions and 329 deletions

View File

@ -387,7 +387,7 @@ namespace cryptonote
crypto::ed25519_public_key owner;
uint16_t type;
std::string name;
std::string value;
std::string value; // binary format of the name->value mapping
BEGIN_SERIALIZE()
FIELD(owner);

View File

@ -3440,7 +3440,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
{
cryptonote::tx_extra_loki_name_system data;
std::string fail_reason;
if (!lns::validate_lns_tx(hf_version, nettype(), tx, &data, nullptr /*lns_value*/, &fail_reason))
if (!lns::validate_lns_tx(hf_version, nettype(), tx, &data, &fail_reason))
{
MERROR_VER("TX type=" << tx.type << ", hash=" << get_transaction_hash(tx) << ", owner=" << data.owner << ", type=" << (int)data.type << ", name=" << data.name << ", reason=" << fail_reason);
return false;

View File

@ -232,225 +232,269 @@ static bool char_is_alphanum(char c)
return result;
}
bool validate_lns_name_and_value(cryptonote::network_type nettype, uint16_t type, char const *name, int name_len, char const *value, int value_len, lns_value *blob, std::string *reason)
bool validate_lns_name(uint16_t type, char const *name, int name_len, std::string *reason)
{
if (blob) *blob = {};
std::stringstream err_stream;
LOKI_DEFER { if (reason) *reason = std::move(err_stream.str()); };
LOKI_DEFER { if (reason) *reason = err_stream.str(); };
// NOTE: Validate value length, and convert the value into a blob if blob is given
int max_name_len = lns::GENERIC_NAME_MAX;
{
cryptonote::address_parse_info addr_info = {};
if (type == static_cast<uint16_t>(mapping_type::blockchain))
{
max_name_len = BLOCKCHAIN_NAME_MAX;
if (value_len == 0 || !get_account_address_from_str(addr_info, nettype, std::string(value, value_len)))
{
if (reason)
{
if (value_len == 0)
{
err_stream << "The name=";
err_stream.write(name, name_len);
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);
}
}
return false;
}
}
else
{
int max_value_len = lns::GENERIC_VALUE_MAX;
bool value_require_exact_len = true;
if (type == static_cast<uint16_t>(mapping_type::lokinet))
{
max_name_len = LOKINET_DOMAIN_NAME_MAX;
max_value_len = (LOKINET_ADDRESS_BINARY_LENGTH * 2);
}
else if (type == static_cast<uint16_t>(mapping_type::messenger))
{
max_name_len = MESSENGER_DISPLAY_NAME_MAX;
max_value_len = (MESSENGER_PUBLIC_KEY_BINARY_LENGTH * 2);
}
else
{
value_require_exact_len = false;
}
if (value_require_exact_len)
{
if (value_len != max_value_len)
{
if (reason)
{
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the value's length=" << value_len << ", does not equal the required length=" << max_value_len << ", given value=";
err_stream.write(value, value_len);
}
return false;
}
}
else
{
if (value_len > max_value_len || value_len == 0)
{
if (reason)
{
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the value's length=" << value_len << " is 0 or exceeds the maximum length=" << max_value_len << ", given value=";
err_stream.write(value, value_len);
}
return false;
}
}
}
if (type == static_cast<uint16_t>(mapping_type::blockchain))
{
if (blob)
{
blob->len = sizeof(addr_info.address);
memcpy(blob->buffer.data(), &addr_info.address, blob->len);
}
}
else
{
// NOTE: Check value is hex
if ((value_len % 2) != 0)
{
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;
}
return false;
}
for (int val_index = 0; val_index < value_len; 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 (blob) // NOTE: Given blob, write the binary output
blob->buffer.data()[blob->len++] = loki::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);
}
return false;
}
}
}
}
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;
// NOTE: Validate name length
if (name_len > max_name_len || name_len == 0)
{
if (name_len > max_name_len || name_len == 0)
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);
}
return false;
}
// NOTE: Validate domain specific requirements
if (type == static_cast<uint16_t>(mapping_type::messenger))
{
}
else if (type == static_cast<uint16_t>(mapping_type::lokinet))
{
// Domain has to start with a letter or digit, and can have letters, digits, or hyphens in between and must end with a .loki
// ^[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 (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);
}
return false;
}
}
if (!char_is_alphanum(name[0])) // Must start with alphanumeric
{
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 << "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);
}
return false;
}
if (type == static_cast<uint16_t>(mapping_type::messenger))
char const SUFFIX[] = ".loki";
char const *name_suffix = name + (name_len - loki::char_count(SUFFIX));
if (memcmp(name_suffix, SUFFIX, loki::char_count(SUFFIX)) != 0) // Must end with .loki
{
// 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'))
if (reason)
{
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);
}
return false;
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);
}
return false;
}
else if (type == static_cast<uint16_t>(mapping_type::lokinet))
char const *char_preceeding_suffix = name_suffix - 1;
if (!char_is_alphanum(char_preceeding_suffix[0])) // Characted preceeding suffix must be alphanumeric
{
// Domain has to start with a letter or digit, and can have letters, digits, or hyphens in between and must end with a .loki
// ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.loki$
if (reason)
{
char const SHORTEST_DOMAIN[] = "a.loki";
if (name_len < 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);
}
return false;
}
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);
}
return false;
}
if (!char_is_alphanum(name[0])) // Must start with alphanumeric
char const *begin = name + 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
{
char c = it[0];
if (!(char_is_alphanum(c) || c == '-'))
{
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 << "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);
}
return false;
}
char const SUFFIX[] = ".loki";
char const *name_suffix = name + (name_len - 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);
}
return false;
}
char const *char_preceeding_suffix = name_suffix - 1;
if (!char_is_alphanum(char_preceeding_suffix[0])) // Characted preceeding suffix must be alphanumeric
{
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);
}
return false;
}
char const *begin = name + 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
{
char c = it[0];
if (!(char_is_alphanum(c) || c == '-'))
{
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);
}
return false;
}
}
}
}
return true;
}
bool validate_lns_tx(uint8_t hf_version, cryptonote::network_type nettype, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system *entry, lns_value *blob, std::string *reason)
static bool check_lengths(uint16_t type, char const *value, int len, int max, bool require_exact_len, std::string *reason)
{
bool result = true;
if (require_exact_len)
{
if (len != max)
result = false;
}
else
{
if (len > max || len == 0)
{
result = false;
}
}
if (!result)
{
if (reason)
{
std::stringstream err_stream;
err_stream << "LNS type=" << type << ", specifies mapping from name -> value where the value's length=" << len;
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);
*reason = err_stream.str();
}
}
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)
{
if (blob) *blob = {};
std::stringstream err_stream;
cryptonote::address_parse_info addr_info = {};
if (type == static_cast<uint16_t>(mapping_type::blockchain))
{
if (value_len == 0 || !get_account_address_from_str(addr_info, nettype, std::string(value, value_len)))
{
if (reason)
{
if (value_len == 0)
{
err_stream << "The value=";
err_stream.write(value, value_len);
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);
}
*reason = err_stream.str();
}
return false;
}
}
else
{
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 value_require_exact_len = false;
if (!check_lengths(type, value, value_len, max_value_len, value_require_exact_len, reason))
return false;
}
if (type == static_cast<uint16_t>(mapping_type::blockchain))
{
if (blob)
{
blob->len = sizeof(addr_info.address);
memcpy(blob->buffer.data(), &addr_info.address, blob->len);
}
}
else
{
// NOTE: Check value is hex
if ((value_len % 2) != 0)
{
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;
*reason = err_stream.str();
}
return false;
}
for (int val_index = 0; val_index < value_len; 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 (blob) // NOTE: Given blob, write the binary output
blob->buffer.data()[blob->len++] = loki::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);
*reason = err_stream.str();
}
return false;
}
}
if (type == static_cast<uint16_t>(mapping_type::messenger))
{
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 (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);
*reason = err_stream.str();
}
return false;
}
}
}
return true;
}
bool validate_lns_value_binary(uint16_t type, char const *value, int value_len, 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);
else value_require_exact_len = false;
if (!check_lengths(type, value, value_len, max_value_len, value_require_exact_len, reason))
return false;
if (type == static_cast<uint16_t>(lns::mapping_type::blockchain))
{
// 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));
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);
*reason = err_stream.str();
}
return false;
}
}
return true;
}
bool validate_lns_tx(uint8_t hf_version, cryptonote::network_type nettype, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system *entry, std::string *reason)
{
cryptonote::tx_extra_loki_name_system entry_;
if (!entry) entry = &entry_;
@ -458,27 +502,39 @@ bool validate_lns_tx(uint8_t hf_version, cryptonote::network_type nettype, crypt
if (!cryptonote::get_loki_name_system_from_tx_extra(tx.extra, *entry))
{
err_stream << "TX: " << tx.type << " " << get_transaction_hash(tx) << ", didn't have loki name service in the tx_extra";
if (reason) *reason = std::move(err_stream.str());
if (reason)
{
err_stream << "TX: " << tx.type << " " << get_transaction_hash(tx) << ", didn't have loki name service in the tx_extra";
*reason = err_stream.str();
}
return false;
}
if (entry->type >= static_cast<uint16_t>(lns::mapping_type::start_reserved) && entry->type <= static_cast<uint16_t>(mapping_type::end_reserved))
{
err_stream << "TX: " << tx.type << " " << get_transaction_hash(tx) << " specifying type = " << static_cast<uint16_t>(entry->type) << " that is unused, but reserved by the protocol";
if (reason) *reason = std::move(err_stream.str());
if (reason)
{
err_stream << "TX: " << tx.type << " " << get_transaction_hash(tx) << " specifying type = " << static_cast<uint16_t>(entry->type) << " that is unused, but reserved by the protocol";
*reason = err_stream.str();
}
return false;
}
uint64_t burn = cryptonote::get_burned_amount_from_tx_extra(tx.extra);
if (!validate_lns_name_and_value(nettype, entry->type, entry->name.data(), static_cast<int>(entry->name.size()), entry->value.data(), static_cast<int>(entry->value.size()), blob, reason))
if (!validate_lns_name(entry->type, entry->name.data(), static_cast<int>(entry->name.size()), reason))
return false;
if (!validate_lns_value_binary(entry->type, entry->value.data(), static_cast<int>(entry->value.size()), reason))
return false;
uint64_t const burn_required = burn_requirement_in_atomic_loki(hf_version);
if (burn != burn_required)
{
err_stream << "LNS TX=" << cryptonote::get_transaction_hash(tx) << ", burned insufficient amounts of loki=" << burn << ", require=" << burn_required;
if (reason) *reason = std::move(err_stream.str());
if (reason)
{
err_stream << "LNS TX=" << cryptonote::get_transaction_hash(tx) << ", burned insufficient amounts of loki=" << burn << ", require=" << burn_required;
*reason = err_stream.str();
}
return false;
}
@ -675,10 +731,9 @@ bool name_system_db::add_block(const cryptonote::block &block, const std::vector
if (tx.type != cryptonote::txtype::loki_name_system)
continue;
lns_value entry_value = {};
cryptonote::tx_extra_loki_name_system entry = {};
std::string fail_reason;
if (!validate_lns_tx(block.major_version, nettype, tx, &entry, &entry_value, &fail_reason))
if (!validate_lns_tx(block.major_version, nettype, tx, &entry, &fail_reason))
{
LOG_PRINT_L1("LNS TX: Failed to validate for tx=" << get_transaction_hash(tx) << ". This should have failed validation earlier reason=" << fail_reason);
assert("Failed to validate acquire name service. Should already have failed validation prior" == nullptr);
@ -701,7 +756,7 @@ bool name_system_db::add_block(const cryptonote::block &block, const std::vector
}
assert(user_id != 0);
if (!save_mapping(static_cast<uint16_t>(entry.type), entry.name, entry_value, height, user_id))
if (!save_mapping(static_cast<uint16_t>(entry.type), entry.name, entry.value, height, user_id))
{
LOG_PRINT_L1("Failed to save LNS entry to DB tx: " << cryptonote::get_transaction_hash(tx)
<< ", type: " << (uint16_t)entry.type
@ -742,12 +797,12 @@ bool name_system_db::save_user(crypto::ed25519_public_key const &key, int64_t *r
return result;
}
bool name_system_db::save_mapping(uint16_t type, std::string const &name, lns_value const &value, uint64_t height, int64_t user_id)
bool name_system_db::save_mapping(uint16_t type, std::string const &name, std::string const &value, uint64_t height, int64_t user_id)
{
sqlite3_stmt *statement = save_mapping_sql;
sqlite3_bind_int (statement, mapping_record_row_type, type);
sqlite3_bind_text (statement, mapping_record_row_name, name.data(), name.size(), nullptr /*destructor*/);
sqlite3_bind_blob (statement, mapping_record_row_value, value.buffer.data(), value.len, nullptr /*destructor*/);
sqlite3_bind_blob (statement, mapping_record_row_value, value.data(), value.size(), nullptr /*destructor*/);
sqlite3_bind_int64(statement, mapping_record_row_register_height, static_cast<int64_t>(height));
sqlite3_bind_int64(statement, mapping_record_row_user_id, user_id);
bool result = sql_run_statement(nettype, lns_sql_type::save_mapping, statement, nullptr);

View File

@ -37,9 +37,15 @@ struct lns_value
uint64_t burn_requirement_in_atomic_loki(uint8_t hf_version);
sqlite3 *init_loki_name_system(char const *file_path);
uint64_t lokinet_expiry_blocks(cryptonote::network_type nettype, uint64_t *renew_window);
bool validate_lns_name_and_value(cryptonote::network_type nettype, uint16_t type, char const *name, int name_len, char const *value, int value_len, lns_value *blob = nullptr, std::string *reason = nullptr);
bool validate_lns_tx(uint8_t hf_version, cryptonote::network_type nettype, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system *entry = nullptr, lns_value *blob = nullptr, std::string *reason = nullptr);
bool validate_lns_name(uint16_t type, char const *name, int name_len, 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_tx(uint8_t hf_version, cryptonote::network_type nettype, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system *entry = nullptr, std::string *reason = nullptr);
bool validate_mapping_type(std::string const &type, uint16_t *mapping_type, std::string *reason);
lns_value convert_value_to_lns_binary_value(uint16_t type, std::string const &value);
struct user_record
{
@ -88,7 +94,7 @@ struct name_system_db
uint64_t height () { return last_processed_height; }
bool save_user (crypto::ed25519_public_key const &key, int64_t *row_id);
bool save_mapping (uint16_t type, std::string const &name, lns_value const &value, uint64_t height, int64_t user_id);
bool save_mapping (uint16_t type, std::string const &name, std::string const &value, uint64_t height, int64_t user_id);
bool save_settings (uint64_t top_height, crypto::hash const &top_hash, int version);
bool expire_mappings(uint64_t height);

View File

@ -8552,7 +8552,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_and_value(nettype(), type, name.data(), name.size(), value.data(), value.size(), nullptr /*lns_value*/, reason))
if (!lns::validate_lns_name(type, name.data(), name.size(), reason))
return {};
lns::lns_value value_blob;
if (!lns::validate_lns_value(nettype(), type, value.data(), value.size(), &value_blob, reason))
return {};
if (priority == tools::tx_priority_blink)
@ -8580,7 +8584,8 @@ std::vector<wallet2::pending_tx> wallet2::create_buy_lns_mapping_tx(uint16_t typ
entry.owner = pkey;
entry.type = type;
entry.name = name;
entry.value = value;
entry.value.resize(value_blob.len);
memcpy(&entry.value[0], value_blob.buffer.data(), value_blob.len);
std::vector<uint8_t> extra;
add_loki_name_system_to_tx_extra(extra, entry);

View File

@ -1439,6 +1439,7 @@ struct loki_chain_generator
cryptonote::transaction create_state_change_tx(service_nodes::new_state state, const crypto::public_key& pub_key, uint64_t height = -1, const std::vector<uint64_t>& voters = {}, uint64_t fee = 0) const;
cryptonote::checkpoint_t create_service_node_checkpoint(uint64_t block_height, size_t num_votes) const;
// value: Takes the binary value NOT the human readable version, of the name->value mapping
static const uint64_t LNS_AUTO_BURN = static_cast<uint64_t>(-1);
cryptonote::transaction create_loki_name_system_tx (cryptonote::account_base const &src, uint16_t type, std::string const &value, std::string const &name, crypto::ed25519_public_key const *owner = nullptr, uint64_t burn = LNS_AUTO_BURN) const;

View File

@ -1014,6 +1014,39 @@ static bool lns_mapping_type_enabled(lns::mapping_type type)
return result;
}
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 lokinet_value;
std::string messenger_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 lokinet_value_hex;
};
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));
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.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.lokinet_value_hex = epee::string_tools::pod_to_hex(result.ed_key);
return result;
}
bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
@ -1044,15 +1077,11 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
gen.add_service_node_checkpoint(gen.height(), service_nodes::CHECKPOINT_MIN_VOTES);
}
crypto::ed25519_public_key miner_key;
crypto::ed25519_secret_key miner_skey;
crypto_sign_ed25519_seed_keypair(miner_key.data, miner_skey.data, reinterpret_cast<const unsigned char *>(miner.get_keys().m_spend_secret_key.data));
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 miner_key_str = epee::string_tools::pod_to_hex(miner_key);
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key_str, name);
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});
uint64_t height_of_lns_entry = gen.height();
@ -1070,16 +1099,16 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
DEFINE_TESTS_ERROR_CONTEXT("check_lns_entries");
lns::name_system_db const &lns_db = c.get_blockchain_storage().name_system_db();
lns::user_record user = lns_db.get_user_by_key(miner_key);
lns::user_record user = lns_db.get_user_by_key(miner_key.ed_key);
CHECK_EQ(user.loaded, true);
CHECK_EQ(user.id, 1);
CHECK_EQ(miner_key, user.key);
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));
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.value, std::string((char *)miner_key.data, sizeof(miner_key)));
CHECK_EQ(mappings.value, miner_key.lokinet_value);
CHECK_EQ(mappings.register_height, height_of_lns_entry);
CHECK_EQ(mappings.user_id, user.id);
return true;
@ -1102,10 +1131,10 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
lns::name_system_db const &lns_db = c.get_blockchain_storage().name_system_db();
// TODO(loki): We should probably expire users that no longer have any mappings remaining
lns::user_record user = lns_db.get_user_by_key(miner_key);
lns::user_record user = lns_db.get_user_by_key(miner_key.ed_key);
CHECK_EQ(user.loaded, true);
CHECK_EQ(user.id, 1);
CHECK_EQ(miner_key, user.key);
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));
CHECK_EQ(mappings.loaded, false);
@ -1155,21 +1184,12 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
gen.add_service_node_checkpoint(gen.height(), service_nodes::CHECKPOINT_MIN_VOTES);
}
crypto::ed25519_public_key bob_key;
crypto::ed25519_secret_key bob_skey;
crypto_sign_ed25519_seed_keypair(bob_key.data, bob_skey.data, reinterpret_cast<const unsigned char *>(bob.get_keys().m_spend_secret_key.data));
// NOTE: Register some messenger names
char messenger_key[lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH] = {};
messenger_key[0] = 5;
memcpy(messenger_key + 1, &bob_key, sizeof(bob_key));
lns_keys_t bob_key = make_lns_keys(bob);
std::string messenger_name1 = "MyName";
std::string messenger_name2 = "AnotherName";
{
std::string messenger_key_hex = epee::string_tools::pod_to_hex(messenger_key);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), messenger_key_hex, messenger_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::messenger), messenger_key_hex, messenger_name2, &bob_key);
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);
gen.create_and_add_next_block({tx1, tx2});
}
uint64_t messenger_height = gen.height();
@ -1178,7 +1198,7 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
{
DEFINE_TESTS_ERROR_CONTEXT("check_lns_entries_before_checkpoint");
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(bob_key);
std::vector<lns::mapping_record> records = lns_db.get_mappings_by_user(bob_key.ed_key);
CHECK_EQ(records.empty(), true);
return true;
});
@ -1189,9 +1209,8 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
if (lns_mapping_type_enabled(lns::mapping_type::lokinet))
{
{
std::string bob_key_str = epee::string_tools::pod_to_hex(bob_key);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::lokinet), bob_key_str, lokinet_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), bob_key_str, lokinet_name2, &bob_key);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::lokinet), bob_key.lokinet_value, lokinet_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), bob_key.lokinet_value, lokinet_name2, &bob_key.ed_key);
gen.create_and_add_next_block({tx1, tx2});
}
}
@ -1204,8 +1223,8 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
{
{
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_addr, wallet_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::blockchain), bob_addr, wallet_name2, &bob_key);
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);
gen.create_and_add_next_block({tx1, tx2});
}
}
@ -1218,19 +1237,15 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
gen.add_service_node_checkpoint(gen.height(), service_nodes::CHECKPOINT_MIN_VOTES);
gen.create_and_add_next_block();
loki_register_callback(events, "check_lns_entries", [&events, bob, bob_key, messenger_key,
loki_register_callback(events, "check_lns_entries", [&events, bob_key,
wallet_height, wallet_name1, wallet_name2,
messenger_height, messenger_name1, messenger_name2,
lokinet_height, lokinet_name1, lokinet_name2
](cryptonote::core &c, size_t ev_index)
{
crypto::ed25519_public_key bob_pkey;
crypto::ed25519_secret_key bob_skey;
crypto_sign_ed25519_seed_keypair(bob_pkey.data, bob_skey.data, reinterpret_cast<const unsigned char *>(bob.get_keys().m_spend_secret_key.data));
DEFINE_TESTS_ERROR_CONTEXT("check_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(bob_pkey);
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;
@ -1238,18 +1253,14 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
if (lns_mapping_type_enabled(lns::mapping_type::lokinet)) expected_size += 2;
CHECK_EQ(records.size(), expected_size);
auto messenger_value_hex_str = std::string(messenger_key, sizeof(messenger_key));
auto lokinet_value_hex_str = std::string((char *)bob_key.data, sizeof(bob_key));
auto wallet_value_str = std::string((char *)&bob.get_keys().m_account_address, sizeof(bob.get_keys().m_account_address));
if (lns_mapping_type_enabled(lns::mapping_type::messenger))
{
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, messenger_value_hex_str);
CHECK_EQ(records[1].value, messenger_value_hex_str);
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));
}
@ -1260,8 +1271,8 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
CHECK_EQ(records[3].name, lokinet_name2);
CHECK_EQ(records[2].register_height, lokinet_height);
CHECK_EQ(records[3].register_height, lokinet_height);
CHECK_EQ(records[2].value, lokinet_value_hex_str);
CHECK_EQ(records[3].value, lokinet_value_hex_str);
CHECK_EQ(records[2].value, bob_key.lokinet_value);
CHECK_EQ(records[3].value, bob_key.lokinet_value);
CHECK_EQ(records[2].type, static_cast<uint16_t>(lns::mapping_type::lokinet));
CHECK_EQ(records[3].type, static_cast<uint16_t>(lns::mapping_type::lokinet));
}
@ -1272,8 +1283,8 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
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, wallet_value_str);
CHECK_EQ(records[5].value, wallet_value_str);
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));
}
@ -1283,38 +1294,6 @@ bool loki_name_system_get_mappings_by_user::generate(std::vector<test_event_entr
return true;
}
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 lokinet_value;
std::string messenger_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 lokinet_value_hex;
};
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));
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.lokinet_value = std::string((char *)result.ed_key.data, sizeof(result.ed_key));
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.lokinet_value_hex = epee::string_tools::pod_to_hex(result.ed_key);
return result;
}
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();
@ -1357,12 +1336,12 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
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_hex, messenger_name);
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.messenger_value_hex, messenger_name);
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);
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_hex, 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, messenger_name);
gen.create_and_add_next_block({bar, bar2, bar3});
}
else
@ -1381,7 +1360,7 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
gen.create_and_add_next_block(); // 2 checkpoints, commit LNS from all new blocks now checkpointed to db
{
cryptonote::transaction bar6 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value_hex, messenger_name);
cryptonote::transaction bar6 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
gen.add_tx(bar6, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in lns db");
}
@ -1471,12 +1450,12 @@ bool loki_name_system_handles_duplicate_in_staging_area::generate(std::vector<te
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_hex, messenger_name);
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.messenger_value_hex, messenger_name);
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);
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_hex, 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, messenger_name);
gen.create_and_add_next_block({bar, bar2, bar3});
}
else
@ -1485,7 +1464,7 @@ bool loki_name_system_handles_duplicate_in_staging_area::generate(std::vector<te
}
// NOTE: Make duplicate, but not checkpointed yet, so in the staging area should be rejected
cryptonote::transaction bar5 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value_hex, messenger_name);
cryptonote::transaction bar5 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
gen.add_tx(bar5, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in staging area");
}
uint64_t height_of_lns_entry = gen.height();
@ -1584,16 +1563,16 @@ bool loki_name_system_handles_duplicate_in_tx_pool::generate(std::vector<test_ev
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_hex, messenger_name);
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.messenger_value_hex, messenger_name);
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);
// 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_hex, messenger_name);
cryptonote::transaction bar4 = gen.create_loki_name_system_tx(bob, static_cast<uint16_t>(lns::mapping_type::messenger), bob_key.messenger_value, messenger_name);
gen.add_tx(bar4, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in tx pool");
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_hex, 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, messenger_name);
gen.create_and_add_next_block({bar, bar2, bar3});
}
else
@ -1665,10 +1644,7 @@ bool loki_name_system_invalid_tx_extra_params::generate(std::vector<test_event_e
gen.add_n_blocks(30); /// generate some outputs and unlock them
gen.add_mined_money_unlock_blocks();
crypto::ed25519_public_key miner_key;
crypto::ed25519_secret_key miner_skey;
crypto_sign_ed25519_seed_keypair(miner_key.data, miner_skey.data, reinterpret_cast<const unsigned char *>(miner.get_keys().m_spend_secret_key.data));
lns_keys_t miner_key = make_lns_keys(miner);
// Manually construct transaction with invalid tx extra
{
auto make_lns_tx_with_custom_extra = [&](loki_chain_generator &gen,
@ -1696,9 +1672,9 @@ 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;
valid_data.owner = miner_key.ed_key;
valid_data.type = static_cast<uint16_t>(lns::mapping_type::blockchain);
valid_data.value = cryptonote::get_account_address_as_str(cryptonote::FAKECHAIN, false, miner.get_keys().m_account_address);
valid_data.value = miner_key.blockchain_value;
valid_data.name = "my_lns_name";
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
@ -1770,21 +1746,17 @@ bool loki_name_system_invalid_tx_extra_params::generate(std::vector<test_event_e
valid_data.type = static_cast<uint16_t>(lns::mapping_type::messenger);
{
cryptonote::tx_extra_loki_name_system data = valid_data;
data.value = std::string(reinterpret_cast<char const *>(miner_key.data), sizeof(miner_key));
stream << "(Messenger) Key invalid, not prefixed with 0x05: " << data.value;
data.value[0] = 'a';
stream << "(Messenger) 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
char messenger_key[lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH] = {};
messenger_key[0] = 5;
memcpy(messenger_key + 1, miner_key.data, sizeof(miner_key));
std::string messenger_key_hex = epee::string_tools::pod_to_hex(messenger_key);
valid_data.value = messenger_key_hex;
valid_data.value = miner_key.messenger_value;
{
cryptonote::tx_extra_loki_name_system data = valid_data;
stream << "(Messenger) Key should be valid, prefixed with 0x05: " << data.value;
stream << "(Messenger) Key should be valid, prefixed with 0x05: " << miner_key.messenger_value_hex;
make_lns_tx_with_custom_extra(gen, events, miner, data, true, stream.str().c_str());
stream.clear();
}
@ -1889,7 +1861,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";
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key.lokinet_value_hex, name);
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});
uint64_t height_of_lns_entry = gen.height();
@ -1928,7 +1900,7 @@ bool loki_name_system_name_renewal::generate(std::vector<test_event_entry> &even
gen.create_and_add_next_block();
// In the renewal window, try and renew the lokinet entry
cryptonote::transaction renew_tx = gen.create_and_add_loki_name_system_tx(miner, static_cast<uint16_t>(lns::mapping_type::lokinet), miner_key.lokinet_value_hex, name);
cryptonote::transaction renew_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({renew_tx});
uint64_t renewal_height = gen.height();
@ -1973,10 +1945,6 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
gen.add_n_blocks(30); /// generate some outputs and unlock them
gen.add_mined_money_unlock_blocks();
crypto::ed25519_public_key pkey;
crypto::ed25519_secret_key skey;
crypto_sign_ed25519_seed_keypair(pkey.data, skey.data, reinterpret_cast<const unsigned char *>(miner.get_keys().m_spend_secret_key.data));
auto make_lns_tx_with_custom_extra = [&](loki_chain_generator &gen,
std::vector<test_event_entry> &events,
cryptonote::account_base const &src,
@ -2000,16 +1968,16 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
gen.add_tx(tx, true /*can_be_added_to_blockchain*/, "", false /*kept_by_block*/);
};
lns_keys_t miner_key = make_lns_keys(miner);
cryptonote::tx_extra_loki_name_system data = {};
data.owner = pkey;
data.value = cryptonote::get_account_address_as_str(cryptonote::FAKECHAIN, false, miner.get_keys().m_account_address);
data.owner = miner_key.ed_key;
// Blockchain
if (lns_mapping_type_enabled(lns::mapping_type::blockchain))
{
data.type = static_cast<uint16_t>(lns::mapping_type::blockchain);
data.name = std::string(lns::BLOCKCHAIN_NAME_MAX, 'A');
data.value = miner.get_public_address_str(cryptonote::FAKECHAIN);
data.value = miner_key.blockchain_value;
make_lns_tx_with_custom_extra(gen, events, miner, data);
}
@ -2018,7 +1986,7 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
{
data.type = static_cast<uint16_t>(lns::mapping_type::lokinet);
data.name = "doyle.loki";
data.value = std::string(lns::LOKINET_ADDRESS_BINARY_LENGTH * 2, 'a');
data.value = std::string(lns::LOKINET_ADDRESS_BINARY_LENGTH, 'a');
make_lns_tx_with_custom_extra(gen, events, miner, data);
}
@ -2026,7 +1994,7 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
{
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 * 2, 'a');
data.value = std::string(lns::MESSENGER_PUBLIC_KEY_BINARY_LENGTH, 'a');
data.value[0] = '0';
data.value[1] = '5';
make_lns_tx_with_custom_extra(gen, events, miner, data);
@ -2070,17 +2038,17 @@ bool loki_name_system_wrong_burn::generate(std::vector<test_event_entry> &events
if (type == lns::mapping_type::messenger)
{
value = lns_keys.messenger_value_hex;
value = lns_keys.messenger_value;
name = "My Friendly Messenger Name";
}
else if (type == lns::mapping_type::blockchain)
{
value = lns_keys.blockchain_value_hex;
value = lns_keys.blockchain_value;
name = "My Friendly Wallet Name";
}
else if (type == lns::mapping_type::lokinet)
{
value = lns_keys.lokinet_value_hex;
value = lns_keys.lokinet_value;
name = "MyFriendlyLokinetName.loki";
}
else

View File

@ -13,52 +13,52 @@ TEST(loki_name_system, lokinet_domain_names)
// Should work
{
char const name[] = "mydomain.loki";
ASSERT_TRUE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_TRUE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "a.loki";
ASSERT_TRUE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_TRUE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "xn--bcher-kva.loki";
ASSERT_TRUE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_TRUE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
// Should fail
{
char const name[] = "";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "mydomain.loki.example";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "mydomain.loki.com";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "mydomain.com";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "mydomain";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "xn--bcher-kva.lok";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
{
char const name[] = "a_b_c.loki";
ASSERT_FALSE(lns::validate_lns_name_and_value(cryptonote::MAINNET, lokinet, name, loki::char_count(name), domain_edkeys, loki::array_count(domain_edkeys)));
ASSERT_FALSE(lns::validate_lns_name(lokinet, name, loki::char_count(name)));
}
}