Add support for backup owners and allow updating LNS fields

This commit is contained in:
Doyle 2020-03-02 15:43:29 +11:00
parent 08ac9bb254
commit 1bff385cac
10 changed files with 463 additions and 412 deletions

View File

@ -65,12 +65,15 @@
namespace lns
{
enum struct tx_command : uint8_t
enum struct extra_field : uint8_t
{
buy,
buy_no_backup,
update,
_count,
owner = 1 << 0,
backup_owner = 1 << 1,
signature = 1 << 2,
encrypted_value = 1 << 3,
buy_no_backup = (extra_field::owner | extra_field::encrypted_value),
buy = (extra_field::buy_no_backup | extra_field::backup_owner),
all = (extra_field::buy | extra_field::signature),
};
};
@ -398,28 +401,30 @@ namespace cryptonote
{
uint8_t version = 0;
lns::mapping_type type;
lns::tx_command command;
crypto::hash name_hash;
crypto::hash prev_txid = crypto::null_hash; // previous txid that purchased the mapping
lns::extra_field fields;
crypto::generic_public_key owner = {}; // only serialized if command == tx_command::buy
crypto::generic_public_key backup_owner = {}; // only serialized if command == tx_command::buy
crypto::generic_signature signature = {}; // only serialized if command == tx_command::update
crypto::hash name_hash;
std::string encrypted_value; // encrypted binary format of the value in the name->value mapping
crypto::hash prev_txid = crypto::null_hash; // previous txid that purchased the mapping
bool is_buying() const { return (command == lns::tx_command::buy || command == lns::tx_command::buy_no_backup); }
constexpr void unset_bit_field (lns::extra_field bit) { fields = static_cast<lns::extra_field>(static_cast<uint8_t>(fields) & ~static_cast<uint8_t>(bit)); }
constexpr void set_bit_field (lns::extra_field bit) { fields = static_cast<lns::extra_field>(static_cast<uint8_t>(fields) | static_cast<uint8_t>(bit)); }
constexpr bool bit_field_is_set (lns::extra_field bit) const { return (static_cast<uint8_t>(fields) & static_cast<uint8_t>(bit)); }
constexpr bool bit_field_match (lns::extra_field bit) const { return ((static_cast<uint8_t>(fields) ^ static_cast<uint8_t>(bit)) == 0); }
constexpr bool is_updating () const { return bit_field_is_set(lns::extra_field::signature); }
constexpr bool is_buying () const { return !is_updating() && (bit_field_is_set(lns::extra_field::buy) || bit_field_is_set(lns::extra_field::buy_no_backup)); }
static tx_extra_loki_name_system make_buy(crypto::generic_public_key const &owner, crypto::generic_public_key const *backup_owner, lns::mapping_type type, crypto::hash const &name_hash, std::string const &encrypted_value, crypto::hash const &prev_txid)
{
tx_extra_loki_name_system result = {};
result.fields = lns::extra_field::buy;
result.owner = owner;
if (backup_owner)
{
result.backup_owner = *backup_owner;
result.command = lns::tx_command::buy;
}
else
{
result.command = lns::tx_command::buy_no_backup;
}
result.fields = lns::extra_field::buy_no_backup;
result.type = type;
result.name_hash = name_hash;
@ -431,33 +436,49 @@ namespace cryptonote
static tx_extra_loki_name_system make_update(crypto::generic_signature const &signature,
lns::mapping_type type,
crypto::hash const &name_hash,
std::string const &encrypted_value,
epee::span<const uint8_t> encrypted_value,
crypto::generic_public_key const *owner,
crypto::generic_public_key const *backup_owner,
crypto::hash const &prev_txid)
{
tx_extra_loki_name_system result = {};
result.signature = signature;
result.type = type;
result.name_hash = name_hash;
result.encrypted_value = encrypted_value;
result.prev_txid = prev_txid;
result.command = lns::tx_command::update;
result.set_bit_field(lns::extra_field::signature);
if (encrypted_value.size())
{
result.set_bit_field(lns::extra_field::encrypted_value);
result.encrypted_value = std::string(reinterpret_cast<char const *>(encrypted_value.data()), encrypted_value.size());
}
if (owner)
{
result.set_bit_field(lns::extra_field::owner);
result.owner = *owner;
}
if (backup_owner)
{
result.set_bit_field(lns::extra_field::backup_owner);
result.backup_owner = *backup_owner;
}
result.prev_txid = prev_txid;
return result;
}
BEGIN_SERIALIZE()
FIELD(version)
ENUM_FIELD(type, type < lns::mapping_type::_count)
ENUM_FIELD(command, command < lns::tx_command::_count)
if (command == lns::tx_command::buy || command == lns::tx_command::buy_no_backup)
{
FIELD(owner)
if (command == lns::tx_command::buy) FIELD(backup_owner);
}
else
FIELD(signature)
FIELD(name_hash)
FIELD(encrypted_value)
FIELD(prev_txid)
ENUM_FIELD(fields, fields <= lns::extra_field::all)
if (bit_field_is_set(lns::extra_field::owner)) FIELD(owner);
if (bit_field_is_set(lns::extra_field::backup_owner)) FIELD(backup_owner);
if (bit_field_is_set(lns::extra_field::signature)) FIELD(signature);
if (bit_field_is_set(lns::extra_field::encrypted_value)) FIELD(encrypted_value);
END_SERIALIZE()
};

View File

@ -1,3 +1,4 @@
#include <bitset>
#include "loki_name_system.h"
#include "checkpoints/checkpoints.h"
@ -238,7 +239,7 @@ static bool sql_compile_statement(sqlite3 *db, char const *query, int query_len,
#endif
bool result = prepare_result == SQLITE_OK;
if (!result) MERROR("Can not compile SQL statement: " << query << ", reason: " << sqlite3_errstr(prepare_result));
if (!result) MERROR("Can not compile SQL statement:\n" << query << "\nReason: " << sqlite3_errstr(prepare_result));
return result;
}
@ -292,23 +293,38 @@ uint64_t expiry_blocks(cryptonote::network_type nettype, mapping_type type, uint
return result;
}
crypto::hash tx_extra_signature_hash(epee::span<const uint8_t> blob, crypto::hash const &prev_txid)
crypto::hash tx_extra_signature_hash(epee::span<const uint8_t> value, crypto::generic_public_key const *owner, crypto::generic_public_key const *backup_owner, crypto::hash const &prev_txid)
{
static_assert(sizeof(crypto::hash) == crypto_generichash_BYTES, "Using libsodium generichash for signature hash, require we fit into crypto::hash");
crypto::hash result = {};
if (blob.size() <= mapping_value::BUFFER_SIZE)
if (value.size() > mapping_value::BUFFER_SIZE)
{
unsigned char buffer[mapping_value::BUFFER_SIZE + sizeof(prev_txid)] = {};
size_t buffer_len = blob.size() + sizeof(prev_txid);
memcpy(buffer, blob.data(), blob.size());
memcpy(buffer + blob.size(), prev_txid.data, sizeof(prev_txid));
crypto_generichash(reinterpret_cast<unsigned char *>(result.data), sizeof(result), buffer, buffer_len, NULL /*key*/, 0 /*key_len*/);
}
else
{
MERROR("Unexpected blob len=" << blob.size() << " greater than the blob backing buffer capacity=" << mapping_value::BUFFER_SIZE);
MERROR("Unexpected value len=" << value.size() << " greater than the expected capacity=" << mapping_value::BUFFER_SIZE);
return result;
}
unsigned char buffer[mapping_value::BUFFER_SIZE + sizeof(*owner) + sizeof(*backup_owner) + sizeof(prev_txid)] = {};
size_t buffer_len = value.size() + sizeof(prev_txid);
if (owner) buffer_len += sizeof(*owner);
if (backup_owner) buffer_len += sizeof(*backup_owner);
unsigned char *ptr = buffer;
memcpy(ptr, value.data(), value.size());
ptr += value.size();
if (owner)
{
memcpy(ptr, owner->data, sizeof(*owner));
ptr += sizeof(*owner);
}
if (backup_owner)
{
memcpy(ptr, backup_owner->data, sizeof(*backup_owner));
ptr += sizeof(*backup_owner);
}
crypto_generichash(reinterpret_cast<unsigned char *>(result.data), sizeof(result), buffer, buffer_len, NULL /*key*/, 0 /*key_len*/);
return result;
}
@ -627,55 +643,90 @@ static bool verify_lns_signature(crypto::hash const &hash, crypto::generic_signa
static bool validate_against_previous_mapping(lns::name_system_db const &lns_db, uint64_t blockchain_height, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system &data, std::string *reason = nullptr)
{
std::stringstream err_stream;
LOKI_DEFER { if (reason && reason->empty()) *reason = err_stream.str(); };
crypto::hash expected_prev_txid = crypto::null_hash;
std::string name_hash = hash_to_base64(data.name_hash);
lns::mapping_record mapping = lns_db.get_mapping(data.type, name_hash);
const bool updating = data.command == lns::tx_command::update;
if (updating && !mapping)
if (data.is_updating() && !mapping)
{
if (reason)
{
err_stream << tx << ", " << data << ", update requested but mapping does not exist.";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", update requested but mapping does not exist.";
return false;
}
if (mapping)
{
expected_prev_txid = mapping.txid;
if (updating) // We can always update unless the mapping has expired
if (data.is_updating())
{
if (!mapping.active(lns_db.network_type(), blockchain_height))
char const SPECIFYING_SAME_VALUE_ERR[] = ", field to update is specifying the same mapping ";
char const VALUE_SPECIFIED_BUT_NOT_REQUESTED[] = ", given field to update but field is not requested to be serialised=";
if (is_lokinet_type(data.type) && !mapping.active(lns_db.network_type(), blockchain_height))
{
if (reason)
{
err_stream << tx << ", " << data << ", TX requested to update mapping that has already expired";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", TX requested to update mapping that has already expired";
return false;
}
if (mapping.encrypted_value == data.encrypted_value)
if (!data.bit_field_is_set(lns::extra_field::owner) &&
!data.bit_field_is_set(lns::extra_field::encrypted_value) &&
!data.bit_field_is_set(lns::extra_field::backup_owner))
{
if (reason)
if (reason) err_stream << tx << ", " << data << ", TX requested to update but specified no fields to update";
return false;
}
if (data.bit_field_is_set(lns::extra_field::encrypted_value))
{
if (mapping.encrypted_value == data.encrypted_value)
{
err_stream << tx << ", " << data << ", value to update to is already the same as the mapping value";
*reason = err_stream.str();
if (reason) err_stream << tx << ", " << data << SPECIFYING_SAME_VALUE_ERR << "value";
return false;
}
}
else if (data.encrypted_value.size())
{
if (reason) err_stream << tx << ", " << data << VALUE_SPECIFIED_BUT_NOT_REQUESTED << "value";
return false;
}
if (data.bit_field_is_set(lns::extra_field::owner))
{
if (data.owner == mapping.owner)
{
if (reason) err_stream << tx << ", " << data << SPECIFYING_SAME_VALUE_ERR << "owner";
return false;
}
}
else if (data.owner.ed25519)
{
if (reason) err_stream << tx << ", " << data << VALUE_SPECIFIED_BUT_NOT_REQUESTED << "owner";
return false;
}
if (data.bit_field_is_set(lns::extra_field::backup_owner))
{
if (data.backup_owner == mapping.backup_owner)
{
if (reason) err_stream << tx << ", " << data << SPECIFYING_SAME_VALUE_ERR << "backup owner";
return false;
}
}
else if (data.backup_owner)
{
if (reason) err_stream << tx << ", " << data << VALUE_SPECIFIED_BUT_NOT_REQUESTED << "backup owner";
return false;
}
// Validate signature
{
crypto::hash hash = tx_extra_signature_hash(epee::strspan<uint8_t>(data.encrypted_value), expected_prev_txid);
auto value = epee::strspan<uint8_t>(data.encrypted_value);
crypto::hash hash = tx_extra_signature_hash(value,
data.bit_field_is_set(lns::extra_field::owner) ? &data.owner : nullptr,
data.bit_field_is_set(lns::extra_field::backup_owner) ? &data.backup_owner : nullptr,
expected_prev_txid);
if (!verify_lns_signature(hash, data.signature, mapping.owner) && !verify_lns_signature(hash, data.signature, mapping.backup_owner))
{
if (reason)
{
err_stream << tx << ", " << data << ", failed to verify signature for LNS update";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", failed to verify signature for LNS update";
return false;
}
}
@ -696,6 +747,12 @@ static bool validate_against_previous_mapping(lns::name_system_db const &lns_db,
return false;
}
if (!(data.bit_field_match(lns::extra_field::buy) || data.bit_field_match(lns::extra_field::buy_no_backup)))
{
if (reason) err_stream << tx << ", " << data << ", TX is buying mapping but serialized unexpected fields not relevant for buying";
return false;
}
uint64_t renew_window = 0;
uint64_t expiry_blocks = lns::expiry_blocks(lns_db.network_type(), data.type, &renew_window);
uint64_t const renew_window_offset = expiry_blocks - renew_window;
@ -718,32 +775,20 @@ static bool validate_against_previous_mapping(lns::name_system_db const &lns_db,
lns::owner_record const requester = lns_db.get_owner_by_key(data.owner);
if (!requester)
{
if (reason)
{
err_stream << tx << ", " << data << ", trying to renew existing mapping but owner specified in LNS extra does not exist, rejected";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", trying to renew existing mapping but owner specified in LNS extra does not exist, rejected";
return false;
}
lns::owner_record const owner = lns_db.get_owner_by_id(mapping.owner_id);
if (!owner)
{
if (reason)
{
err_stream << tx << ", " << data << ", unexpected owner_id=" << mapping.owner_id << " does not exist";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", unexpected owner_id=" << mapping.owner_id << " does not exist";
return false;
}
if (requester.id != owner.id)
{
if (reason)
{
err_stream << tx << ", " << data << ", actual owner=" << owner.key << ", with owner_id=" << mapping.owner_id << ", does not match requester=" << requester.key << ", with id=" << requester.id;
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", actual owner=" << owner.key << ", with owner_id=" << mapping.owner_id << ", does not match requester=" << requester.key << ", with id=" << requester.id;
return false;
}
}
@ -753,11 +798,7 @@ static bool validate_against_previous_mapping(lns::name_system_db const &lns_db,
if (data.prev_txid != expected_prev_txid)
{
if (reason)
{
err_stream << tx << ", " << data << ", specified prior owner txid=" << data.prev_txid << ", but LNS DB reports=" << expected_prev_txid << ", possible competing TX was submitted and accepted before this TX was processed";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << data << ", specified prior owner txid=" << data.prev_txid << ", but LNS DB reports=" << expected_prev_txid << ", possible competing TX was submitted and accepted before this TX was processed";
return false;
}
@ -766,83 +807,67 @@ static bool validate_against_previous_mapping(lns::name_system_db const &lns_db,
bool name_system_db::validate_lns_tx(uint8_t hf_version, uint64_t blockchain_height, cryptonote::transaction const &tx, cryptonote::tx_extra_loki_name_system *entry, std::string *reason) const
{
std::stringstream err_stream;
LOKI_DEFER { if (reason && reason->empty()) *reason = err_stream.str(); };
cryptonote::tx_extra_loki_name_system entry_;
if (!entry) entry = &entry_;
std::stringstream err_stream;
if (tx.type != cryptonote::txtype::loki_name_system)
{
if (reason)
{
err_stream << tx << ", uses wrong tx type, expected=" << cryptonote::txtype::loki_name_system;
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", uses wrong tx type, expected=" << cryptonote::txtype::loki_name_system;
return false;
}
if (!cryptonote::get_loki_name_system_from_tx_extra(tx.extra, *entry))
{
if (reason)
{
err_stream << tx << ", didn't have loki name service in the tx_extra";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", didn't have loki name service in the tx_extra";
return false;
}
if (entry->version != 0)
{
if (reason)
{
err_stream << tx << ", " << *entry << ", unexpected version=" << std::to_string(entry->version) << ", expected=0";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << *entry << ", unexpected version=" << std::to_string(entry->version) << ", expected=0";
return false;
}
if (!lns::mapping_type_allowed(hf_version, entry->type))
{
if (reason)
{
err_stream << tx << ", " << *entry << ", specifying type=" << entry->type << " that is disallowed";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << *entry << ", specifying type=" << entry->type << " that is disallowed";
return false;
}
if (entry->is_buying())
{
if (entry->owner == entry->backup_owner)
if (!entry->owner)
{
if (reason)
{
err_stream << tx << ", " << *entry << ", specifying owner the same as the backup owner";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << *entry << ", can't specify LNS extra without owner";
return false;
}
if (!entry->owner)
if (entry->owner == entry->backup_owner)
{
if (reason)
{
err_stream << tx << ", " << *entry << ", can't specify LNS extra without owner";
*reason = err_stream.str();
}
if (reason) err_stream << tx << ", " << *entry << ", specifying owner the same as the backup owner";
return false;
}
}
else if (entry->is_updating())
{
if (!entry->signature)
{
if (reason) err_stream << tx << ", " << *entry << ", signature to validate is the null-signature";
return false;
}
}
else
{
if (!entry->signature)
if (reason)
{
if (reason)
{
err_stream << tx << ", " << *entry << ", signature to validate is the null-signature";
*reason = err_stream.str();
}
return false;
err_stream << tx << ", " << *entry
<< ", TX extra does not specify valid combination of bits in serialized fields="
<< std::bitset<sizeof(entry->fields) * 8>(static_cast<size_t>(entry->fields));
}
return false;
}
if (!validate_encrypted_mapping_value(entry->type, entry->encrypted_value, reason))
@ -1158,7 +1183,7 @@ static int64_t add_or_get_owner_id(lns::name_system_db &lns_db, crypto::hash con
if (owner_record owner = lns_db.get_owner_by_key(key)) result = owner.id;
if (result == 0)
{
if (entry.command == lns::tx_command::update)
if (entry.is_updating())
{
MERROR("Owner does not exist but TX received is trying to update an existing mapping (i.e. owner should already exist). TX=" << tx_hash << " should have failed validation prior.");
return result;
@ -1450,7 +1475,7 @@ std::vector<mapping_record> name_system_db::get_mappings(std::vector<uint16_t> c
if (!sql_compile_statement(db, sql_statement.c_str(), sql_statement.size(), &statement, false /*optimise_for_multiple_usage*/))
return result;
sqlite3_bind_text(statement, 1 /*sql param index*/, name.data(), name.size(), nullptr /*destructor*/);
sqlite3_bind_text(statement, 1 /*sql param index*/, name_base64_hash.data(), name_base64_hash.size(), nullptr /*destructor*/);
// Execute
sql_run_statement(nettype, lns_sql_type::get_mappings, statement, &result);

View File

@ -65,7 +65,7 @@ sqlite3 *init_loki_name_system(char const *file_path);
uint64_t constexpr NO_EXPIRY = static_cast<uint64_t>(-1);
// return: The number of blocks until expiry from the registration height, if there is no expiration NO_EXPIRY is returned.
uint64_t expiry_blocks(cryptonote::network_type nettype, mapping_type type, uint64_t *renew_window = nullptr);
crypto::hash tx_extra_signature_hash(epee::span<const uint8_t> blob, crypto::hash const &prev_txid);
crypto::hash tx_extra_signature_hash(epee::span<const uint8_t> value, crypto::generic_public_key const *owner, crypto::generic_public_key const *backup_owner, crypto::hash const &prev_txid);
bool validate_lns_name(mapping_type type, std::string const &name, std::string *reason = nullptr);
// Validate a human readable mapping value representation in 'value' and write the binary form into 'blob'.

View File

@ -271,11 +271,12 @@ namespace
const char* USAGE_REQUEST_STAKE_UNLOCK("request_stake_unlock <service_node_pubkey>");
const char* USAGE_PRINT_LOCKED_STAKES("print_locked_stakes");
const char* USAGE_LNS_BUY_MAPPING("lns_buy_mapping [index=<N1>[,<N2>,...]] [<priority>] [owner=] [backup_owner=] \"<name>\" <value>");
const char* USAGE_LNS_UPDATE_MAPPING("lns_update_mapping [index=<N1>[,<N2>,...]] [<priority>] \"<name>\" <value> [<signature>]");
const char* USAGE_LNS_BUY_MAPPING("lns_buy_mapping [index=<N1>[,<N2>,...]] [<priority>] [owner=<pub_key>] [backup_owner=<pub_key>] \"<name>\" <value>");
const char* USAGE_LNS_UPDATE_MAPPING(
"lns_update_mapping [index=<N1>[,<N2>,...]] [<priority>] [owner=<pub_key>] [backup_owner=<pub_key>] [value=<lns_value>] [signature=<hex_signature>] \"<name>\"");
// TODO(loki): Currently defaults to session, in future allow specifying Lokinet and Wallet when they are enabled
const char* USAGE_LNS_MAKE_UPDATE_MAPPING_SIGNATURE("lns_make_update_mapping_signature \"<name>\" <new_value>");
const char* USAGE_LNS_MAKE_UPDATE_MAPPING_SIGNATURE("lns_make_update_mapping_signature [owner=<pub_key>] [backup_owner=<pub_key>] [value=<lns_value>] \"<name>\"");
const char* USAGE_LNS_PRINT_OWNERS_TO_NAMES("lns_print_owners_to_names [<64 hex character ed25519 public key>]");
const char* USAGE_LNS_PRINT_NAME_TO_OWNERS("lns_print_name_to_owners [type=<N1|all>[,<N2>...]] \"name\"");
@ -6343,15 +6344,26 @@ bool simple_wallet::print_locked_stakes(const std::vector<std::string>& /*args*/
return true;
}
//----------------------------------------------------------------------------------------------------
static bool parse_lns_name_string(std::vector<std::string> const &args, size_t first_word_index, size_t last_word_index, std::string &name)
static bool parse_lns_name_string(const char *usage, std::vector<std::string> const &args, size_t first_word_index, size_t last_word_index, std::string &name)
{
if (args.empty())
{
PRINT_USAGE(usage);
fail_msg_writer() << "Missing name argument in args (args is empty)";
return false;
}
// NOTE: Potentially passed in a valid multi worded quoted string (i.e "String World") as the name to purchase.
// Strip the first and last quote, keep everything inbetween, even quotes.
std::string const &first_word = args[first_word_index];
std::string const &last_word = args[last_word_index];
if (first_word.front() != '"' || last_word.back() != '"')
{
PRINT_USAGE(usage);
fail_msg_writer() << "lns name didn't start or end with quotation marks (\"), first word in name=" << first_word << ", last word=" << last_word;
return false;
}
for (size_t i = first_word_index; i <= last_word_index; i++)
{
@ -6372,6 +6384,26 @@ static bool parse_lns_name_string(std::vector<std::string> const &args, size_t f
return true;
}
//----------------------------------------------------------------------------------------------------
std::string eat_named_argument(std::vector<std::string> &args, char const *prefix, size_t prefix_len)
{
std::string result = {};
for (auto it = args.begin(); it != args.end(); it++)
{
if (it->size() > prefix_len && memcmp(it->data(), prefix, prefix_len) == 0)
{
result = it->substr(prefix_len, it->size() - prefix_len);
args.erase(it);
break;
}
}
return result;
}
//----------------------------------------------------------------------------------------------------
constexpr char const LNS_OWNER_PREFIX[] = "owner=";
constexpr char const LNS_BACKUP_OWNER_PREFIX[] = "backup_owner=";
constexpr char const LNS_VALUE_PREFIX[] = "value=";
constexpr char const LNS_SIGNATURE_PREFIX[] = "signature=";
bool simple_wallet::lns_buy_mapping(const std::vector<std::string>& args)
{
std::vector<std::string> local_args = args;
@ -6385,42 +6417,15 @@ bool simple_wallet::lns_buy_mapping(const std::vector<std::string>& args)
return true;
}
std::string owner = {};
std::string backup_owner = {};
{
char const OWNER_PREFIX[] = "owner=";
char const BACKUP_OWNER_PREFIX[] = "backup_owner=";
for (auto it = local_args.begin(); it != local_args.end();)
{
// Check prefix of argument is <owner>= and extract keys out
if (it->size() > loki::char_count(OWNER_PREFIX) && memcmp(it->data(), OWNER_PREFIX, loki::char_count(OWNER_PREFIX)) == 0)
{
owner = it->substr(loki::char_count(OWNER_PREFIX), it->size() - loki::char_count(OWNER_PREFIX));
it = local_args.erase(it);
}
else if (it->size() > loki::char_count(BACKUP_OWNER_PREFIX) && memcmp(it->data(), BACKUP_OWNER_PREFIX, loki::char_count(BACKUP_OWNER_PREFIX)) == 0)
{
backup_owner = it->substr(loki::char_count(BACKUP_OWNER_PREFIX), it->size() - loki::char_count(BACKUP_OWNER_PREFIX));
it = local_args.erase(it);
}
else
{
it++;
}
}
}
std::string owner = eat_named_argument(local_args, LNS_OWNER_PREFIX, loki::char_count(LNS_OWNER_PREFIX));
std::string backup_owner = eat_named_argument(local_args, LNS_BACKUP_OWNER_PREFIX, loki::char_count(LNS_BACKUP_OWNER_PREFIX));
std::string const &value = local_args[local_args.size() - 1];
std::string name;
size_t first_word_index = 0;
size_t last_word_index = local_args.size() - 2;
if (!parse_lns_name_string(local_args, first_word_index, last_word_index, name))
{
PRINT_USAGE(USAGE_LNS_BUY_MAPPING);
fail_msg_writer() << "lns name didn't start or end with quotation marks (\"), first word in name is=\"" << local_args[first_word_index] << "\"";
if (!parse_lns_name_string(USAGE_LNS_BUY_MAPPING, local_args, first_word_index, last_word_index, name))
return false;
}
SCOPED_WALLET_UNLOCK();
std::string reason;
@ -6429,7 +6434,7 @@ bool simple_wallet::lns_buy_mapping(const std::vector<std::string>& args)
{
ptx_vector = m_wallet->lns_create_buy_mapping_tx(lns::mapping_type::session,
owner,
backup_owner,
backup_owner.size() ? &backup_owner : nullptr,
name,
value,
&reason,
@ -6472,41 +6477,15 @@ bool simple_wallet::lns_update_mapping(const std::vector<std::string>& args)
std::set<uint32_t> subaddr_indices = {};
if (!parse_subaddr_indices_and_priority(*m_wallet, local_args, subaddr_indices, priority)) return false;
if (local_args.size() < 2)
{
PRINT_USAGE(USAGE_LNS_UPDATE_MAPPING);
return true;
}
std::string const *signature = nullptr;
std::string const *value = nullptr;
std::string const &last_word = local_args[local_args.size() - 1];
if (last_word.size() == (sizeof(crypto::signature) * 2))
{
if (local_args.size() == 2)
{
PRINT_USAGE(USAGE_LNS_UPDATE_MAPPING);
fail_msg_writer() << "Detected signature=" << last_word << ", but only 2 arguments given- missing either <value> or \"<name>\".";
return true;
}
signature = &last_word;
value = &local_args[local_args.size() - 2];
}
else
{
value = &last_word;
}
std::string owner = eat_named_argument(local_args, LNS_OWNER_PREFIX, loki::char_count(LNS_OWNER_PREFIX));
std::string backup_owner = eat_named_argument(local_args, LNS_BACKUP_OWNER_PREFIX, loki::char_count(LNS_BACKUP_OWNER_PREFIX));
std::string value = eat_named_argument(local_args, LNS_VALUE_PREFIX, loki::char_count(LNS_VALUE_PREFIX));
std::string signature = eat_named_argument(local_args, LNS_SIGNATURE_PREFIX, loki::char_count(LNS_SIGNATURE_PREFIX));
std::string name;
size_t first_word_index = 0;
size_t last_word_index = local_args.size() - 2;
if (!parse_lns_name_string(local_args, first_word_index, last_word_index, name))
{
PRINT_USAGE(USAGE_LNS_UPDATE_MAPPING);
fail_msg_writer() << "lns name didn't start or end with quotation marks (')";
if (!parse_lns_name_string(USAGE_LNS_UPDATE_MAPPING, local_args, 0, local_args.size() - 1, name))
return false;
}
SCOPED_WALLET_UNLOCK();
std::string reason;
@ -6515,8 +6494,10 @@ bool simple_wallet::lns_update_mapping(const std::vector<std::string>& args)
{
ptx_vector = m_wallet->lns_create_update_mapping_tx(lns::mapping_type::session,
name,
*value,
signature,
value.size() ? &value : nullptr,
owner.size() ? &owner : nullptr,
backup_owner.size() ? &backup_owner : nullptr,
signature.size() ? &signature : nullptr,
&reason,
priority,
m_current_subaddress_account,
@ -6555,26 +6536,26 @@ bool simple_wallet::lns_make_update_mapping_signature(const std::vector<std::str
if (!try_connect_to_daemon())
return true;
if (args.size() < 2)
{
PRINT_USAGE(USAGE_LNS_MAKE_UPDATE_MAPPING_SIGNATURE);
return true;
}
std::vector<std::string> local_args = args;
std::string owner = eat_named_argument(local_args, LNS_OWNER_PREFIX, loki::char_count(LNS_OWNER_PREFIX));
std::string backup_owner = eat_named_argument(local_args, LNS_BACKUP_OWNER_PREFIX, loki::char_count(LNS_BACKUP_OWNER_PREFIX));
std::string value = eat_named_argument(local_args, LNS_VALUE_PREFIX, loki::char_count(LNS_VALUE_PREFIX));
std::string const &new_value = args.back();
std::string name;
if (!parse_lns_name_string(args, 0, (args.size() - 2), name))
{
PRINT_USAGE(USAGE_LNS_MAKE_UPDATE_MAPPING_SIGNATURE);
fail_msg_writer() << "lns name didn't start or end with quotation marks (\")";
if (!parse_lns_name_string(USAGE_LNS_MAKE_UPDATE_MAPPING_SIGNATURE, local_args, 0, local_args.size() - 1, name))
return true;
}
SCOPED_WALLET_UNLOCK();
crypto::generic_signature signature;
crypto::generic_signature signature_binary;
std::string reason;
if (m_wallet->lns_make_update_mapping_signature(lns::mapping_type::session, name, new_value, signature, &reason))
tools::success_msg_writer() << "signature=" << epee::string_tools::pod_to_hex(signature);
if (m_wallet->lns_make_update_mapping_signature(lns::mapping_type::session,
name,
value.size() ? &value : nullptr,
owner.size() ? &owner : nullptr,
backup_owner.size() ? &backup_owner : nullptr,
signature_binary,
&reason))
tools::success_msg_writer() << "signature=" << epee::string_tools::pod_to_hex(signature_binary);
else
fail_msg_writer() << reason;
@ -6627,12 +6608,8 @@ bool simple_wallet::lns_print_name_to_owners(const std::vector<std::string>& arg
}
std::string lns_name;
if (!parse_lns_name_string(args, start_of_name, end_of_name, lns_name))
{
PRINT_USAGE(USAGE_LNS_PRINT_NAME_TO_OWNERS);
fail_msg_writer() << "lns name didn't start or end with quotation marks (\")";
if (!parse_lns_name_string(USAGE_LNS_PRINT_NAME_TO_OWNERS, args, start_of_name, end_of_name, lns_name))
return false;
}
cryptonote::COMMAND_RPC_LNS_NAMES_TO_OWNERS::request request = {};
request.entries.push_back({lns_name, std::move(requested_types)});

View File

@ -8427,56 +8427,73 @@ wallet2::request_stake_unlock_result wallet2::can_request_stake_unlock(const cry
return result;
}
static bool prepare_tx_extra_loki_name_system_values(cryptonote::network_type nettype,
lns::mapping_type type,
uint32_t priority,
std::string const &name,
std::string const &value,
wallet2 const &wallet,
crypto::hash &prev_txid,
lns::mapping_value &encrypted_value,
std::string *reason)
struct lns_prepared_args
{
bool prepared;
operator bool() const { return prepared; }
lns::mapping_value encrypted_value;
crypto::hash name_hash;
crypto::generic_public_key owner;
crypto::generic_public_key backup_owner;
crypto::generic_signature signature;
crypto::hash prev_txid;
};
static lns_prepared_args prepare_tx_extra_loki_name_system_values(wallet2 const &wallet,
lns::mapping_type type,
uint32_t priority,
std::string const &name,
std::string const *value,
std::string const *owner,
std::string const *backup_owner,
bool make_signature,
std::string *reason)
{
lns_prepared_args result = {};
if (priority == tools::tx_priority_blink)
{
if (reason) *reason = "Can not request a blink TX for Loki Name Service transactions";
return false;
return result;
}
boost::optional<uint8_t> hf_version = wallet.get_hard_fork_version();
if (!hf_version)
if (!lns::validate_lns_name(type, name, reason))
return result;
result.name_hash = lns::name_to_hash(name);
if (value)
{
if (reason) *reason = ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
return false;
}
lns::mapping_value binary_value = {};
if (!lns::validate_mapping_value(wallet.nettype(), type, *value, &binary_value, reason))
return result;
// Make encrypted value
{
if (!lns::validate_lns_name(type, name, reason))
return false;
if (!lns::mapping_type_allowed(*hf_version, type))
if (!lns::encrypt_mapping_value(name, binary_value, result.encrypted_value))
{
if (reason)
{
*reason = "Mapping type not allowed=";
reason->append(lns::mapping_type_str(type));
}
return false;
}
lns::mapping_value blob = {};
if (!lns::validate_mapping_value(nettype, type, value, &blob, reason))
return false;
if (!lns::encrypt_mapping_value(name, blob, encrypted_value))
{
if (reason) *reason = "Failed to encrypt LNS value=" + value;
return false;
if (reason) *reason = "Fail to encrypt mapping value=" + *value;
return {};
}
}
prev_txid = crypto::null_hash;
if (owner)
{
if (!epee::string_tools::hex_to_pod(*owner, result.owner))
{
if (reason) *reason = "Hex owner key provided failed to convert to public_key, owner=" + *owner;
return {};
}
}
if (backup_owner)
{
if (!epee::string_tools::hex_to_pod(*backup_owner, result.backup_owner))
{
if (reason) *reason = "Hex backup_owner key provided failed to convert to public_key, backup_owner=" + *backup_owner;
return {};
}
}
if (!owner && !backup_owner)
result.owner.monero = wallet.get_account().get_keys().m_account_address.m_spend_public_key;
{
cryptonote::COMMAND_RPC_LNS_NAMES_TO_OWNERS::request request = {};
{
@ -8491,30 +8508,38 @@ static bool prepare_tx_extra_loki_name_system_values(cryptonote::network_type ne
if (failed)
{
if (reason) *reason = "Failed to query previous owner for LNS entry, reason=" + *failed;
return false;
return result;
}
if (response.size())
{
crypto::hash txid_hash = {};
if (epee::string_tools::hex_to_pod(response[0].txid, txid_hash))
{
prev_txid = txid_hash;
}
else
if (!epee::string_tools::hex_to_pod(response[0].txid, result.prev_txid))
{
if (reason) *reason = "Failed to convert response txid=" + response[0].txid + " from the daemon into a 32 byte hash, it must be a 64 char hex string";
return false;
return result;
}
}
}
return true;
if (make_signature)
{
crypto::hash hash = lns::tx_extra_signature_hash(result.encrypted_value.to_span(),
owner ? &result.owner : nullptr,
backup_owner ? &result.backup_owner : nullptr,
result.prev_txid);
crypto::generate_signature(hash,
wallet.get_account().get_keys().m_account_address.m_spend_public_key,
wallet.get_account().get_keys().m_spend_secret_key,
result.signature.monero);
}
result.prepared = true;
return result;
}
std::vector<wallet2::pending_tx> wallet2::lns_create_buy_mapping_tx(lns::mapping_type type,
std::string const &owner,
std::string const &backup_owner,
std::string const *backup_owner,
std::string const &name,
std::string const &value,
std::string *reason,
@ -8522,45 +8547,18 @@ std::vector<wallet2::pending_tx> wallet2::lns_create_buy_mapping_tx(lns::mapping
uint32_t account_index,
std::set<uint32_t> subaddr_indices)
{
crypto::generic_public_key owner_pkey = {};
crypto::generic_public_key backup_owner_pkey = {};
if (owner.empty() && backup_owner.empty())
{
owner_pkey.monero = m_account.get_keys().m_account_address.m_spend_public_key;
}
else
{
if (owner.size())
{
if (!epee::string_tools::hex_to_pod(owner, owner_pkey))
{
if (reason) *reason = "Failed to convert owner to a public key, owner=" + owner_pkey;
return {};
}
}
if (backup_owner.size())
{
if (!epee::string_tools::hex_to_pod(backup_owner, backup_owner_pkey))
{
if (reason) *reason = "Failed to convert backup owner to a public key, backup_owner=" + backup_owner;
return {};
}
}
}
lns::mapping_value encrypted_value;
crypto::hash prev_txid;
if (!prepare_tx_extra_loki_name_system_values(nettype(), type, priority, name, value, *this, prev_txid, encrypted_value, reason))
lns_prepared_args prepared_args = prepare_tx_extra_loki_name_system_values(*this, type, priority, name, &value, &owner, backup_owner, false /*make_signature*/, reason);
if (!prepared_args)
return {};
std::vector<uint8_t> extra;
auto entry = cryptonote::tx_extra_loki_name_system::make_buy(owner_pkey,
backup_owner.size() ? &backup_owner_pkey : nullptr,
type,
lns::name_to_hash(name),
encrypted_value.to_string(),
prev_txid);
auto entry = cryptonote::tx_extra_loki_name_system::make_buy(
prepared_args.owner,
backup_owner ? &prepared_args.backup_owner : nullptr,
type,
prepared_args.name_hash,
prepared_args.encrypted_value.to_string(),
prepared_args.prev_txid);
add_loki_name_system_to_tx_extra(extra, entry);
boost::optional<uint8_t> hf_version = get_hard_fork_version();
@ -8584,7 +8582,7 @@ std::vector<wallet2::pending_tx> wallet2::lns_create_buy_mapping_tx(lns::mapping
std::vector<wallet2::pending_tx> wallet2::lns_create_buy_mapping_tx(std::string const &type,
std::string const &owner,
std::string const &backup_owner,
std::string const *backup_owner,
std::string const &name,
std::string const &value,
std::string *reason,
@ -8602,38 +8600,43 @@ std::vector<wallet2::pending_tx> wallet2::lns_create_buy_mapping_tx(std::string
std::vector<wallet2::pending_tx> wallet2::lns_create_update_mapping_tx(lns::mapping_type type,
std::string const &name,
std::string const &value,
std::string const *value,
std::string const *owner,
std::string const *backup_owner,
std::string const *signature,
std::string *reason,
uint32_t priority,
uint32_t account_index,
std::set<uint32_t> subaddr_indices)
{
crypto::hash prev_txid;
lns::mapping_value value_blob;
if (!prepare_tx_extra_loki_name_system_values(nettype(), type, priority, name, value, *this, prev_txid, value_blob, reason))
return {};
crypto::generic_public_key pkey;
crypto::generic_signature signature_binary;
if (signature)
if (!value && !owner && !backup_owner)
{
if (!epee::string_tools::hex_to_pod(*signature, signature_binary))
if (reason) *reason = "Value, owner and backup owner are not specified. Atleast one field must be specified for updating the LNS record";
return {};
}
bool make_signature = signature == nullptr;
lns_prepared_args prepared_args = prepare_tx_extra_loki_name_system_values(*this, type, priority, name, value, owner, backup_owner, make_signature, reason);
if (!prepared_args) return {};
if (!make_signature)
{
if (!epee::string_tools::hex_to_pod(*signature, prepared_args.signature))
{
if (reason) *reason = "Hex signature provided failed to convert to a ed25519_signature, signature=" + *signature;
return {};
}
}
else
{
crypto::hash hash = lns::tx_extra_signature_hash(epee::span<const uint8_t>(value_blob.buffer.data(), value_blob.len), prev_txid);
crypto::generate_signature(hash, m_account.get_keys().m_account_address.m_spend_public_key, m_account.get_keys().m_spend_secret_key, signature_binary.monero);
}
std::vector<uint8_t> extra;
auto entry = cryptonote::tx_extra_loki_name_system::make_update(signature_binary, type, lns::name_to_hash(name), std::string(reinterpret_cast<char const *>(value_blob.buffer.data()), value_blob.len), prev_txid);
auto entry = cryptonote::tx_extra_loki_name_system::make_update(prepared_args.signature,
type,
prepared_args.name_hash,
prepared_args.encrypted_value.to_span(),
owner ? &prepared_args.owner : nullptr,
backup_owner ? &prepared_args.backup_owner : nullptr,
prepared_args.prev_txid);
add_loki_name_system_to_tx_extra(extra, entry);
boost::optional<uint8_t> hf_version = get_hard_fork_version();
if (!hf_version)
{
@ -8655,7 +8658,9 @@ std::vector<wallet2::pending_tx> wallet2::lns_create_update_mapping_tx(lns::mapp
std::vector<wallet2::pending_tx> wallet2::lns_create_update_mapping_tx(std::string const &type,
std::string const &name,
std::string const &value,
std::string const *value,
std::string const *owner,
std::string const *backup_owner,
std::string const *signature,
std::string *reason,
uint32_t priority,
@ -8666,7 +8671,7 @@ std::vector<wallet2::pending_tx> wallet2::lns_create_update_mapping_tx(std::stri
if (!lns::validate_mapping_type(type, &mapping_type, reason))
return {};
std::vector<wallet2::pending_tx> result = lns_create_update_mapping_tx(mapping_type, name, value, signature, reason, priority, account_index, subaddr_indices);
std::vector<wallet2::pending_tx> result = lns_create_update_mapping_tx(mapping_type, name, value, owner, backup_owner, signature, reason, priority, account_index, subaddr_indices);
return result;
}
@ -8692,21 +8697,24 @@ bool wallet2::unlock_keys_file()
return true;
}
bool wallet2::lns_make_update_mapping_signature(lns::mapping_type type, std::string const &name, std::string const &value, crypto::generic_signature &signature, std::string *reason)
bool wallet2::lns_make_update_mapping_signature(lns::mapping_type type,
std::string const &name,
std::string const *value,
std::string const *owner,
std::string const *backup_owner,
crypto::generic_signature &signature,
std::string *reason)
{
crypto::hash prev_txid = crypto::null_hash;
lns::mapping_value value_blob;
if (!prepare_tx_extra_loki_name_system_values(nettype(), type, tx_priority_unimportant, name, value, *this, prev_txid, value_blob, reason))
return false;
lns_prepared_args prepared_args = prepare_tx_extra_loki_name_system_values(*this, type, tx_priority_unimportant, name, value, owner, backup_owner, true /*make_signature*/, reason);
if (!prepared_args) return false;
if (prev_txid == crypto::null_hash)
if (prepared_args.prev_txid == crypto::null_hash)
{
if (reason) *reason = "name=\"" + name + std::string("\" does not have a corresponding LNS record, the mapping is available for purchase, update signature is not required.");
return false;
}
crypto::hash hash = lns::tx_extra_signature_hash(value_blob.to_span(), prev_txid);
crypto::generate_signature(hash, get_account().get_keys().m_account_address.m_spend_public_key, get_account().get_keys().m_spend_secret_key, signature.monero);
signature = std::move(prepared_args.signature);
return true;
}

View File

@ -1538,16 +1538,16 @@ private:
pending_tx ptx;
};
request_stake_unlock_result can_request_stake_unlock(const crypto::public_key &sn_key);
std::vector<wallet2::pending_tx> lns_create_buy_mapping_tx(lns::mapping_type type, std::string const &owner, std::string const &backup_owner, std::string const &name, std::string const &value, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
std::vector<wallet2::pending_tx> lns_create_buy_mapping_tx(std::string const &type, std::string const &owner, std::string const &backup_owner, std::string const &name, std::string const &value, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
std::vector<wallet2::pending_tx> lns_create_buy_mapping_tx(lns::mapping_type type, std::string const &owner, std::string const *backup_owner, std::string const &name, std::string const &value, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
std::vector<wallet2::pending_tx> lns_create_buy_mapping_tx(std::string const &type, std::string const &owner, std::string const *backup_owner, std::string const &name, std::string const &value, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
// signature: (Optional) If set, use the signature given, otherwise by default derive the signature from the wallet spend key as an ed25519 key.
// The signature is derived from the hash of the previous txid blob and previous value blob of the mapping. By default this is signed using the wallet's spend key as an ed25519 keypair.
std::vector<wallet2::pending_tx> lns_create_update_mapping_tx(lns::mapping_type type, std::string const &name, std::string const &value, std::string const *signature, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
std::vector<wallet2::pending_tx> lns_create_update_mapping_tx(std::string const &type, std::string const &name, std::string const &value, std::string const *signature, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
std::vector<wallet2::pending_tx> lns_create_update_mapping_tx(lns::mapping_type type, std::string const &name, std::string const *value, std::string const *owner, std::string const *backup_owner, std::string const *signature, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
std::vector<wallet2::pending_tx> lns_create_update_mapping_tx(std::string const &type, std::string const &name, std::string const *value, std::string const *owner, std::string const *backup_owner, std::string const *signature, std::string *reason, uint32_t priority = 0, uint32_t account_index = 0, std::set<uint32_t> subaddr_indices = {});
// Generate just the signature required for putting into lns_update_mapping command in the wallet
bool lns_make_update_mapping_signature(lns::mapping_type type, std::string const &name, std::string const &value, crypto::generic_signature &signature, std::string *reason = nullptr);
bool lns_make_update_mapping_signature(lns::mapping_type type, std::string const &name, std::string const *value, std::string const *owner, std::string const *backup_owner, crypto::generic_signature &signature, std::string *reason = nullptr);
void freeze(size_t idx);
void thaw(size_t idx);

View File

@ -4293,7 +4293,7 @@ namespace tools
std::string reason;
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->lns_create_buy_mapping_tx(req.type,
req.owner,
req.backup_owner,
req.backup_owner.size() ? &req.backup_owner : nullptr,
req.name,
req.value,
&reason,
@ -4338,8 +4338,10 @@ namespace tools
std::vector<wallet2::pending_tx> ptx_vector =
m_wallet->lns_create_update_mapping_tx(req.type,
req.name,
req.value,
req.signature.empty() ? nullptr : &req.signature,
req.value.empty() ? nullptr : &req.value,
req.owner.empty() ? nullptr : &req.owner,
req.backup_owner.empty() ? nullptr : &req.backup_owner,
req.signature.empty() ? nullptr : &req.signature,
&reason,
req.priority,
req.account_index,
@ -4389,7 +4391,13 @@ namespace tools
}
crypto::generic_signature signature;
if (!m_wallet->lns_make_update_mapping_signature(type, req.name, req.value, signature, &reason))
if (!m_wallet->lns_make_update_mapping_signature(type,
req.name,
req.value.size() ? &req.value : nullptr,
req.owner.size() ? &req.owner : nullptr,
req.backup_owner.size() ? &req.backup_owner : nullptr,
signature,
&reason))
{
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
er.message = "Failed to create signature for LNS update transaction: " + reason;

View File

@ -285,13 +285,13 @@ void loki_chain_generator::add_tx(cryptonote::transaction const &tx, bool can_be
cryptonote::transaction
loki_chain_generator::create_and_add_loki_name_system_tx(cryptonote::account_base const &src,
lns::mapping_type type,
lns::mapping_value const &value,
std::string const &name,
lns::mapping_value const &value,
crypto::generic_public_key const *owner,
crypto::generic_public_key const *backup_owner,
bool kept_by_block)
{
cryptonote::transaction t = create_loki_name_system_tx(src, type, value, name, owner, backup_owner);
cryptonote::transaction t = create_loki_name_system_tx(src, type, name, value, owner, backup_owner);
add_tx(t, true /*can_be_added_to_blockchain*/, ""/*fail_msg*/, kept_by_block);
return t;
}
@ -299,12 +299,14 @@ loki_chain_generator::create_and_add_loki_name_system_tx(cryptonote::account_bas
cryptonote::transaction
loki_chain_generator::create_and_add_loki_name_system_tx_update(cryptonote::account_base const &src,
lns::mapping_type type,
lns::mapping_value const &value,
std::string const &name,
lns::mapping_value const *value,
crypto::generic_public_key const *owner,
crypto::generic_public_key const *backup_owner,
crypto::generic_signature *signature,
bool kept_by_block)
{
cryptonote::transaction t = create_loki_name_system_tx_update(src, type, value, name, signature);
cryptonote::transaction t = create_loki_name_system_tx_update(src, type, name, value, owner, backup_owner, signature);
add_tx(t, true /*can_be_added_to_blockchain*/, ""/*fail_msg*/, kept_by_block);
return t;
}
@ -517,8 +519,8 @@ cryptonote::checkpoint_t loki_chain_generator::create_service_node_checkpoint(ui
cryptonote::transaction loki_chain_generator::create_loki_name_system_tx(cryptonote::account_base const &src,
lns::mapping_type type,
lns::mapping_value const &value,
std::string const &name,
lns::mapping_value const &value,
crypto::generic_public_key const *owner,
crypto::generic_public_key const *backup_owner,
uint64_t burn) const
@ -565,8 +567,10 @@ cryptonote::transaction loki_chain_generator::create_loki_name_system_tx(crypton
cryptonote::transaction loki_chain_generator::create_loki_name_system_tx_update(cryptonote::account_base const &src,
lns::mapping_type type,
lns::mapping_value const &value,
std::string const &name,
lns::mapping_value const *value,
crypto::generic_public_key const *owner,
crypto::generic_public_key const *backup_owner,
crypto::generic_signature *signature,
bool use_asserts) const
{
@ -576,20 +580,25 @@ cryptonote::transaction loki_chain_generator::create_loki_name_system_tx_update(
crypto::hash prev_txid = mapping.txid;
if (use_asserts) assert(mapping);
lns::mapping_value encrypted_value = {};
bool encrypted = lns::encrypt_mapping_value(name, value, encrypted_value);
if (use_asserts) assert(encrypted);
epee::span<const uint8_t> value_span = {};
if (value)
{
lns::mapping_value encrypted_value = {};
bool encrypted = lns::encrypt_mapping_value(name, *value, encrypted_value);
if (use_asserts) assert(encrypted);
value_span = encrypted_value.to_span();
}
crypto::generic_signature signature_ = {};
if (!signature)
{
signature = &signature_;
crypto::hash hash = lns::tx_extra_signature_hash(epee::span<const uint8_t>(reinterpret_cast<const uint8_t *>(encrypted_value.buffer.data()), encrypted_value.len), prev_txid);
crypto::hash hash = lns::tx_extra_signature_hash(value_span, owner, backup_owner, prev_txid);
crypto::generate_signature(hash, src.get_keys().m_account_address.m_spend_public_key, src.get_keys().m_spend_secret_key, signature->monero);
}
std::vector<uint8_t> extra;
cryptonote::tx_extra_loki_name_system data = cryptonote::tx_extra_loki_name_system::make_update(*signature, type, name_hash, encrypted_value.to_string(), prev_txid);
cryptonote::tx_extra_loki_name_system data = cryptonote::tx_extra_loki_name_system::make_update(*signature, type, name_hash, value_span, owner, backup_owner, prev_txid);
cryptonote::add_loki_name_system_to_tx_extra(extra, data);
cryptonote::block const &head = top().block;

View File

@ -1421,8 +1421,8 @@ struct loki_chain_generator
// NOTE: Add constructed TX to events_ and assume that it is valid to add to the blockchain. If the TX is meant to be unaddable to the blockchain use the individual create + add functions to
// be able to mark the add TX event as something that should trigger a failure.
cryptonote::transaction create_and_add_loki_name_system_tx(cryptonote::account_base const &src, lns::mapping_type type, lns::mapping_value const &value, std::string const &name, crypto::generic_public_key const *owner = nullptr, crypto::generic_public_key const *backup_owner = nullptr, bool kept_by_block = false);
cryptonote::transaction create_and_add_loki_name_system_tx_update(cryptonote::account_base const &src, lns::mapping_type type, lns::mapping_value const &value, std::string const &name, crypto::generic_signature *signature = nullptr, bool kept_by_block = false);
cryptonote::transaction create_and_add_loki_name_system_tx(cryptonote::account_base const &src, lns::mapping_type type, std::string const &name, lns::mapping_value const &value, crypto::generic_public_key const *owner = nullptr, crypto::generic_public_key const *backup_owner = nullptr, bool kept_by_block = false);
cryptonote::transaction create_and_add_loki_name_system_tx_update(cryptonote::account_base const &src, lns::mapping_type type, std::string const &name, lns::mapping_value const *value, crypto::generic_public_key const *owner = nullptr, crypto::generic_public_key const *backup_owner = nullptr, crypto::generic_signature *signature = nullptr, bool kept_by_block = false);
cryptonote::transaction create_and_add_tx (const cryptonote::account_base& src, const cryptonote::account_public_address& dest, uint64_t amount, uint64_t fee = TESTS_DEFAULT_FEE, bool kept_by_block = false);
cryptonote::transaction create_and_add_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, bool kept_by_block = false);
cryptonote::transaction create_and_add_registration_tx(const cryptonote::account_base& src, const cryptonote::keypair& sn_keys = cryptonote::keypair::generate(hw::get_device("default")), bool kept_by_block = false);
@ -1443,8 +1443,8 @@ struct loki_chain_generator
// 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, lns::mapping_type type, lns::mapping_value const &value, std::string const &name, crypto::generic_public_key const *owner = nullptr, crypto::generic_public_key const *backup_owner = nullptr, uint64_t burn = LNS_AUTO_BURN) const;
cryptonote::transaction create_loki_name_system_tx_update(cryptonote::account_base const &src, lns::mapping_type type, lns::mapping_value const &value, std::string const &name, crypto::generic_signature *signature = nullptr, bool use_asserts = false) const;
cryptonote::transaction create_loki_name_system_tx(cryptonote::account_base const &src, lns::mapping_type type, std::string const &name, lns::mapping_value const &value, crypto::generic_public_key const *owner = nullptr, crypto::generic_public_key const *backup_owner = nullptr, uint64_t burn = LNS_AUTO_BURN) const;
cryptonote::transaction create_loki_name_system_tx_update(cryptonote::account_base const &src, lns::mapping_type type, std::string const &name, lns::mapping_value const *value, crypto::generic_public_key const *owner = nullptr, crypto::generic_public_key const *backup_owner = nullptr, crypto::generic_signature *signature = nullptr, bool use_asserts = false) const;
cryptonote::transaction create_loki_name_system_tx_update_w_extra(cryptonote::account_base const &src, cryptonote::tx_extra_loki_name_system const &lns_extra) const;
loki_blockchain_entry create_genesis_block(const cryptonote::account_base &miner, uint64_t timestamp);

View File

@ -1039,7 +1039,7 @@ bool loki_name_system_disallow_reserved_type::generate(std::vector<test_event_en
auto unusable_type = static_cast<lns::mapping_type>(-1);
assert(!lns::mapping_type_allowed(gen.hardfork(), unusable_type));
cryptonote::transaction tx1 = gen.create_loki_name_system_tx(miner, unusable_type, mapping_value, "FriendlyName");
cryptonote::transaction tx1 = gen.create_loki_name_system_tx(miner, unusable_type, "FriendlyName", mapping_value);
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;
}
@ -1086,7 +1086,7 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
std::string const name = "mydomain.loki";
if (lns::mapping_type_allowed(gen.hardfork(), mapping_type))
{
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, mapping_type, miner_key.lokinet_value, name);
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, mapping_type, name, miner_key.lokinet_value);
gen.create_and_add_next_block({tx});
crypto::hash tx_hash = cryptonote::get_transaction_hash(tx);
@ -1130,7 +1130,7 @@ bool loki_name_system_expiration::generate(std::vector<test_event_entry> &events
}
else
{
cryptonote::transaction tx = gen.create_loki_name_system_tx(miner, mapping_type, miner_key.lokinet_value, name);
cryptonote::transaction tx = gen.create_loki_name_system_tx(miner, mapping_type, name, miner_key.lokinet_value);
gen.add_tx(tx, false /*can_be_added_to_blockchain*/, "Can not add LNS TX that uses disallowed type");
}
}
@ -1161,8 +1161,8 @@ bool loki_name_system_get_mappings_by_owner::generate(std::vector<test_event_ent
std::string session_name2 = "AnotherName";
crypto::hash session_name1_txid = {}, session_name2_txid = {};
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, bob_key.session_value, session_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, bob_key.session_value, session_name2, &bob_key.key);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, session_name1, bob_key.session_value);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, session_name2, bob_key.session_value, &bob_key.key);
gen.create_and_add_next_block({tx1, tx2});
session_name1_txid = get_transaction_hash(tx1);
session_name2_txid = get_transaction_hash(tx2);
@ -1175,8 +1175,8 @@ bool loki_name_system_get_mappings_by_owner::generate(std::vector<test_event_ent
crypto::hash lokinet_name1_txid = {}, lokinet_name2_txid = {};
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::lokinet_1year))
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::lokinet_1year, bob_key.lokinet_value, lokinet_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, bob_key.lokinet_value, lokinet_name2, &bob_key.key);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::lokinet_1year, lokinet_name1, bob_key.lokinet_value);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, lokinet_name2, bob_key.lokinet_value, &bob_key.key);
gen.create_and_add_next_block({tx1, tx2});
lokinet_name1_txid = get_transaction_hash(tx1);
lokinet_name2_txid = get_transaction_hash(tx2);
@ -1190,8 +1190,8 @@ bool loki_name_system_get_mappings_by_owner::generate(std::vector<test_event_ent
if (lns::mapping_type_allowed(gen.hardfork(), 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, lns::mapping_type::wallet, bob_key.wallet_value, wallet_name1);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::wallet, bob_key.wallet_value, wallet_name2, &bob_key.key);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::wallet, wallet_name1, bob_key.wallet_value);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::wallet, wallet_name2, bob_key.wallet_value, &bob_key.key);
gen.create_and_add_next_block({tx1, tx2});
wallet_name1_txid = get_transaction_hash(tx1);
wallet_name2_txid = get_transaction_hash(tx2);
@ -1257,7 +1257,7 @@ bool loki_name_system_get_mappings_by_owners::generate(std::vector<test_event_en
std::string session_name1 = "MyName";
crypto::hash session_tx_hash1;
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, bob_key.session_value, session_name1);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, session_name1, bob_key.session_value);
session_tx_hash1 = cryptonote::get_transaction_hash(tx1);
gen.create_and_add_next_block({tx1});
}
@ -1266,7 +1266,7 @@ bool loki_name_system_get_mappings_by_owners::generate(std::vector<test_event_en
std::string session_name2 = "MyName2";
crypto::hash session_tx_hash2;
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, bob_key.session_value, session_name2);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, session_name2, bob_key.session_value);
session_tx_hash2 = cryptonote::get_transaction_hash(tx1);
gen.create_and_add_next_block({tx1});
}
@ -1275,7 +1275,7 @@ bool loki_name_system_get_mappings_by_owners::generate(std::vector<test_event_en
std::string session_name3 = "MyName3";
crypto::hash session_tx_hash3;
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, session_name3);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, session_name3, miner_key.session_value);
session_tx_hash3 = cryptonote::get_transaction_hash(tx1);
gen.create_and_add_next_block({tx1});
}
@ -1324,7 +1324,7 @@ bool loki_name_system_get_mappings::generate(std::vector<test_event_entry> &even
std::string session_name1 = "MyName";
crypto::hash session_tx_hash;
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, bob_key.session_value, session_name1);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, session_name1, bob_key.session_value);
session_tx_hash = cryptonote::get_transaction_hash(tx1);
gen.create_and_add_next_block({tx1});
}
@ -1368,7 +1368,7 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
crypto::hash session_tx_hash = {}, lokinet_tx_hash = {};
{
// NOTE: Allow duplicates with the same name but different type
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, bob_key.session_value, session_name);
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, session_name, bob_key.session_value);
session_tx_hash = get_transaction_hash(bar);
std::vector<cryptonote::transaction> txs;
@ -1376,7 +1376,7 @@ bool loki_name_system_handles_duplicate_in_lns_db::generate(std::vector<test_eve
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::lokinet_1year))
{
cryptonote::transaction bar3 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, miner_key.lokinet_value, session_name);
cryptonote::transaction bar3 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, session_name, miner_key.lokinet_value);
txs.push_back(bar3);
lokinet_tx_hash = get_transaction_hash(bar3);
}
@ -1386,7 +1386,7 @@ 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, lns::mapping_type::session, bob_key.session_value, session_name);
cryptonote::transaction bar6 = gen.create_loki_name_system_tx(bob, lns::mapping_type::session, session_name, bob_key.session_value);
gen.add_tx(bar6, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in lns db");
}
@ -1442,13 +1442,13 @@ bool loki_name_system_handles_duplicate_in_tx_pool::generate(std::vector<test_ev
auto custom_type = static_cast<lns::mapping_type>(3928);
{
// NOTE: Allow duplicates with the same name but different type
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, bob_key.session_value, session_name);
cryptonote::transaction bar = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, session_name, bob_key.session_value);
if (lns::mapping_type_allowed(gen.hardfork(), custom_type))
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, bob_key.session_value, session_name);
cryptonote::transaction bar2 = gen.create_and_add_loki_name_system_tx(miner, custom_type, session_name, bob_key.session_value);
// NOTE: Make duplicate in the TX pool, this should be rejected
cryptonote::transaction bar4 = gen.create_loki_name_system_tx(bob, lns::mapping_type::session, bob_key.session_value, session_name);
cryptonote::transaction bar4 = gen.create_loki_name_system_tx(bob, lns::mapping_type::session, session_name, bob_key.session_value);
gen.add_tx(bar4, false /*can_be_added_to_blockchain*/, "Duplicate name requested by new owner: original already exists in tx pool");
}
return true;
@ -1493,10 +1493,11 @@ bool loki_name_system_invalid_tx_extra_params::generate(std::vector<test_event_e
std::string name = "my_lns_name";
cryptonote::tx_extra_loki_name_system valid_data = {};
valid_data.owner = miner_key.key;
valid_data.type = lns::mapping_type::wallet;
valid_data.encrypted_value = helper_encrypt_lns_value(name, miner_key.wallet_value).to_string();
valid_data.name_hash = lns::name_to_hash("my_lns_name");
valid_data.set_bit_field(lns::extra_field::buy_no_backup);
valid_data.owner = miner_key.key;
valid_data.type = lns::mapping_type::wallet;
valid_data.encrypted_value = helper_encrypt_lns_value(name, miner_key.wallet_value).to_string();
valid_data.name_hash = lns::name_to_hash(name);
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::wallet))
{
@ -1615,20 +1616,20 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
// NOTE: Generate and add the (transactions + block) to the blockchain
{
std::vector<cryptonote::transaction> txs;
cryptonote::transaction session_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, session_name1);
cryptonote::transaction session_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, session_name1, miner_key.session_value);
session_tx_hash1 = get_transaction_hash(session_tx);
txs.push_back(session_tx);
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::wallet))
{
cryptonote::transaction wallet_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::wallet, miner_key.wallet_value, wallet_name1);
cryptonote::transaction wallet_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::wallet, wallet_name1, miner_key.wallet_value);
txs.push_back(wallet_tx);
wallet_tx_hash1 = get_transaction_hash(wallet_tx);
}
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::lokinet_1year))
{
cryptonote::transaction lokinet_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, miner_key.lokinet_value, lokinet_name1);
cryptonote::transaction lokinet_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, lokinet_name1, miner_key.lokinet_value);
txs.push_back(lokinet_tx);
lokinet_tx_hash1 = get_transaction_hash(lokinet_tx);
}
@ -1682,11 +1683,11 @@ bool loki_name_system_large_reorg::generate(std::vector<test_event_entry> &event
crypto::hash session_tx_hash2 = {}, lokinet_tx_hash2 = {};
{
std::vector<cryptonote::transaction> txs;
txs.push_back(gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, bob_key.session_value, bob_session_name1));
txs.push_back(gen.create_and_add_loki_name_system_tx(bob, lns::mapping_type::session, bob_session_name1, bob_key.session_value));
session_tx_hash2 = cryptonote::get_transaction_hash(txs[0]);
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::lokinet_1year))
txs.push_back(gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, miner_key.lokinet_value, "loki.loki"));
txs.push_back(gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, "loki.loki", miner_key.lokinet_value));
gen.create_and_add_next_block(txs);
}
second_lns_height = gen.height();
@ -1814,7 +1815,7 @@ bool loki_name_system_name_renewal::generate(std::vector<test_event_entry> &even
lns_keys_t miner_key = make_lns_keys(miner);
std::string const name = "mydomain.loki";
lns::mapping_type mapping_type = lns::mapping_type::lokinet_1year;
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, mapping_type, miner_key.lokinet_value, name);
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, mapping_type, name, miner_key.lokinet_value);
gen.create_and_add_next_block({tx});
crypto::hash prev_txid = get_transaction_hash(tx);
@ -1843,7 +1844,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, lns::mapping_type::lokinet_1year, miner_key.lokinet_value, name);
cryptonote::transaction renew_tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, name, miner_key.lokinet_value);
gen.create_and_add_next_block({renew_tx});
crypto::hash txid = cryptonote::get_transaction_hash(renew_tx);
uint64_t renewal_height = gen.height();
@ -1901,6 +1902,7 @@ bool loki_name_system_name_value_max_lengths::generate(std::vector<test_event_en
lns_keys_t miner_key = make_lns_keys(miner);
cryptonote::tx_extra_loki_name_system data = {};
data.set_bit_field(lns::extra_field::buy_no_backup);
data.owner = miner_key.key;
// Wallet
@ -1956,7 +1958,7 @@ bool loki_name_system_update_mapping_after_expiry_fails::generate(std::vector<te
if (lns::mapping_type_allowed(gen.hardfork(), lns::mapping_type::lokinet_1year))
{
std::string const name = "mydomain.loki";
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, miner_key.lokinet_value, name);
cryptonote::transaction tx = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::lokinet_1year, name, miner_key.lokinet_value);
crypto::hash tx_hash = cryptonote::get_transaction_hash(tx);
gen.create_and_add_next_block({tx});
@ -1968,7 +1970,7 @@ bool loki_name_system_update_mapping_after_expiry_fails::generate(std::vector<te
{
lns_keys_t bob_key = make_lns_keys(gen.add_account());
cryptonote::transaction tx1 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::lokinet_1year, bob_key.lokinet_value, name);
cryptonote::transaction tx1 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::lokinet_1year, name, &bob_key.lokinet_value);
gen.add_tx(tx1, false /*can_be_added_to_blockchain*/, "Can not update a LNS record that is already expired");
}
@ -2008,20 +2010,20 @@ bool loki_name_system_update_mapping::generate(std::vector<test_event_entry> &ev
crypto::hash session_tx_hash1;
std::string session_name1 = "MyName";
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, session_name1);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, session_name1, miner_key.session_value);
session_tx_hash1 = cryptonote::get_transaction_hash(tx1);
gen.create_and_add_next_block({tx1});
}
// Test update mapping with same name fails
{
cryptonote::transaction tx1 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::session, miner_key.session_value, session_name1);
cryptonote::transaction tx1 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::session, session_name1, &miner_key.session_value);
gen.add_tx(tx1, false /*can_be_added_to_blockchain*/, "Can not add a LNS TX that re-updates the underlying value to same value");
}
crypto::hash session_tx_hash2;
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, bob_key.session_value, session_name1);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, session_name1, &bob_key.session_value);
session_tx_hash2 = cryptonote::get_transaction_hash(tx1);
gen.create_and_add_next_block({tx1});
}
@ -2065,7 +2067,7 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
crypto_sign_ed25519_keypair(owner2.data, owner2_key.data);
std::string name = "Hello World";
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, name, &owner1, &owner2);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, name, miner_key.session_value, &owner1, &owner2);
gen.create_and_add_next_block({tx1});
uint64_t height = gen.height();
crypto::hash txid = cryptonote::get_transaction_hash(tx1);
@ -2085,10 +2087,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto_sign_detached(signature.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash), owner1_key.data);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2109,10 +2111,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto_sign_detached(signature.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash), owner2_key.data);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
uint64_t height = gen.height();
prev_txid = txid;
@ -2140,7 +2142,7 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
crypto::generate_keys(owner2.monero, owner2_key);
std::string name = "Hello Sailor";
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, name, &owner1, &owner2);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, name, miner_key.session_value, &owner1, &owner2);
gen.create_and_add_next_block({tx1});
uint64_t height = gen.height();
crypto::hash txid = cryptonote::get_transaction_hash(tx1);
@ -2151,10 +2153,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto::generate_signature(hash, owner1.monero, owner1_key, signature.monero);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2175,10 +2177,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto::generate_signature(hash, owner2.monero, owner2_key, signature.monero);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2206,7 +2208,7 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
crypto::generate_keys(owner2.monero, owner2_key);
std::string name = "Hello Driver";
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, name, &owner1, &owner2);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, name, miner_key.session_value, &owner1, &owner2);
gen.create_and_add_next_block({tx1});
uint64_t height = gen.height();
crypto::hash txid = cryptonote::get_transaction_hash(tx1);
@ -2217,10 +2219,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto_sign_detached(signature.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash), owner1_key.data);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2241,10 +2243,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto::generate_signature(hash, owner2.monero, owner2_key, signature.monero);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2272,7 +2274,7 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
crypto_sign_ed25519_keypair(owner2.data, owner2_key.data);
std::string name = "Hello Passenger";
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, name, &owner1, &owner2);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, name, miner_key.session_value, &owner1, &owner2);
gen.create_and_add_next_block({tx1});
uint64_t height = gen.height();
crypto::hash txid = cryptonote::get_transaction_hash(tx1);
@ -2283,10 +2285,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto::generate_signature(hash, owner1.monero, owner1_key, signature.monero);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2307,10 +2309,10 @@ bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_
lns_keys_t temp_keys = make_lns_keys(gen.add_account());
crypto::generic_signature signature;
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), txid);
crypto::hash hash = lns::tx_extra_signature_hash(temp_keys.session_value.to_span(), nullptr /*owner*/, nullptr /*backup_owner*/, txid);
crypto_sign_detached(signature.data, NULL, reinterpret_cast<unsigned char *>(hash.data), sizeof(hash), owner2_key.data);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, temp_keys.session_value, name, &signature);
cryptonote::transaction tx2 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &temp_keys.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &signature);
gen.create_and_add_next_block({tx2});
height = gen.height();
prev_txid = txid;
@ -2339,7 +2341,8 @@ bool loki_name_system_update_mapping_non_existent_name_fails::generate(std::vect
cryptonote::account_base miner = gen.first_miner_;
lns_keys_t miner_key = make_lns_keys(miner);
cryptonote::transaction tx1 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::session, miner_key.session_value, "Hello World", nullptr /*signature*/, false /*use_asserts*/);
std::string name = "Hello World";
cryptonote::transaction tx1 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &miner_key.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, nullptr /*signature*/, false /*use_asserts*/);
gen.add_tx(tx1, false /*can_be_added_to_blockchain*/, "Can not add a updating LNS TX referencing a non-existent LNS entry");
return true;
}
@ -2356,12 +2359,12 @@ bool loki_name_system_update_mapping_invalid_signature::generate(std::vector<tes
lns_keys_t miner_key = make_lns_keys(miner);
std::string const name = "Hello World";
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, name);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, name, miner_key.session_value);
gen.create_and_add_next_block({tx1});
lns_keys_t bob_key = make_lns_keys(gen.add_account());
crypto::generic_signature invalid_signature = {};
cryptonote::transaction tx2 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::session, bob_key.session_value, name, &invalid_signature, false /*use_asserts*/);
cryptonote::transaction tx2 = gen.create_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &bob_key.session_value, nullptr /*owner*/, nullptr /*backup_owner*/, &invalid_signature, false /*use_asserts*/);
gen.add_tx(tx2, false /*can_be_added_to_blockchain*/, "Can not add a updating LNS TX with an invalid signature");
return true;
}
@ -2382,14 +2385,14 @@ bool loki_name_system_update_mapping_replay::generate(std::vector<test_event_ent
std::string const name = "Hello World";
// Make LNS Mapping
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, miner_key.session_value, name);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx(miner, lns::mapping_type::session, name, miner_key.session_value);
gen.create_and_add_next_block({tx1});
}
// (1) Update LNS Mapping
cryptonote::tx_extra_loki_name_system lns_entry = {};
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, bob_key.session_value, name);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &bob_key.session_value);
gen.create_and_add_next_block({tx1});
assert(cryptonote::get_loki_name_system_from_tx_extra(tx1.extra, lns_entry));
}
@ -2402,7 +2405,7 @@ bool loki_name_system_update_mapping_replay::generate(std::vector<test_event_ent
// (2) Update Again
{
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, alice_key.session_value, name);
cryptonote::transaction tx1 = gen.create_and_add_loki_name_system_tx_update(miner, lns::mapping_type::session, name, &alice_key.session_value);
gen.create_and_add_next_block({tx1});
}
@ -2464,7 +2467,7 @@ bool loki_name_system_wrong_burn::generate(std::vector<test_event_entry> &events
if (under_burn) burn -= 1;
else burn += 1;
cryptonote::transaction tx = gen.create_loki_name_system_tx(miner, type, value, name, nullptr /*owner*/, nullptr /*backup_owner*/, burn);
cryptonote::transaction tx = gen.create_loki_name_system_tx(miner, type, name, value, nullptr /*owner*/, nullptr /*backup_owner*/, burn);
gen.add_tx(tx, false /*can_be_added_to_blockchain*/, "Wrong burn for a LNS tx", false /*kept_by_block*/);
}
}