mirror of https://github.com/oxen-io/oxen-core.git
Update SQL commands to handle backup owner keys
This commit is contained in:
parent
43f7119cb1
commit
aefdbbcae4
|
@ -401,7 +401,7 @@ namespace cryptonote
|
|||
lns::tx_command command;
|
||||
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::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
|
||||
|
|
|
@ -69,6 +69,7 @@ enum struct mapping_record_row
|
|||
prev_txid,
|
||||
register_height,
|
||||
owner_id,
|
||||
backup_owner_id,
|
||||
_count,
|
||||
};
|
||||
|
||||
|
@ -139,9 +140,10 @@ static bool sql_run_statement(cryptonote::network_type nettype, lns_sql_type typ
|
|||
if (type_int >= tools::enum_count<mapping_type>)
|
||||
return false;
|
||||
|
||||
tmp_entry.type = static_cast<mapping_type>(type_int);
|
||||
tmp_entry.type = static_cast<mapping_type>(type_int);
|
||||
tmp_entry.register_height = static_cast<uint16_t>(sqlite3_column_int(statement, static_cast<int>(mapping_record_row::register_height)));
|
||||
tmp_entry.owner_id = sqlite3_column_int(statement, static_cast<int>(mapping_record_row::owner_id));
|
||||
tmp_entry.owner_id = sqlite3_column_int(statement, static_cast<int>(mapping_record_row::owner_id));
|
||||
tmp_entry.backup_owner_id = sqlite3_column_int(statement, static_cast<int>(mapping_record_row::backup_owner_id));
|
||||
|
||||
// Copy encrypted_value
|
||||
{
|
||||
|
@ -169,10 +171,16 @@ static bool sql_run_statement(cryptonote::network_type nettype, lns_sql_type typ
|
|||
if (!sql_copy_blob(statement, static_cast<int>(mapping_record_row::prev_txid), tmp_entry.prev_txid.data, sizeof(tmp_entry.prev_txid)))
|
||||
return false;
|
||||
|
||||
int last_column = tools::enum_count<mapping_record_row> + 1;
|
||||
if (!sql_copy_blob(statement, last_column, tmp_entry.owner.data, sizeof(tmp_entry.owner)))
|
||||
int owner_column = tools::enum_count<mapping_record_row>;
|
||||
if (!sql_copy_blob(statement, owner_column, tmp_entry.owner.data, sizeof(tmp_entry.owner)))
|
||||
return false;
|
||||
|
||||
if (tmp_entry.backup_owner_id > 0)
|
||||
{
|
||||
if (!sql_copy_blob(statement, owner_column + 1, tmp_entry.backup_owner.data, sizeof(tmp_entry.backup_owner)))
|
||||
return false;
|
||||
}
|
||||
|
||||
data_loaded = true;
|
||||
if (type == lns_sql_type::get_mapping)
|
||||
{
|
||||
|
@ -659,7 +667,7 @@ static bool validate_against_previous_mapping(lns::name_system_db const &lns_db,
|
|||
|
||||
// Validate signature
|
||||
{
|
||||
crypto::hash hash = tx_extra_signature_hash(epee::span<const uint8_t>(reinterpret_cast<const uint8_t *>(data.encrypted_value.data()), data.encrypted_value.size()), expected_prev_txid);
|
||||
crypto::hash hash = tx_extra_signature_hash(epee::strspan<uint8_t>(data.encrypted_value), expected_prev_txid);
|
||||
if (!verify_lns_signature(hash, data.signature, mapping.owner) && !verify_lns_signature(hash, data.signature, mapping.backup_owner))
|
||||
{
|
||||
if (reason)
|
||||
|
@ -820,6 +828,18 @@ bool name_system_db::validate_lns_tx(uint8_t hf_version, uint64_t blockchain_hei
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!entry->signature)
|
||||
{
|
||||
if (reason)
|
||||
{
|
||||
err_stream << tx << ", " << *entry << ", signature to validate is the null-signature";
|
||||
*reason = err_stream.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!validate_encrypted_mapping_value(entry->type, entry->encrypted_value, reason))
|
||||
return false;
|
||||
|
@ -978,7 +998,8 @@ CREATE TABLE IF NOT EXISTS "mappings" (
|
|||
"txid" BLOB NOT NULL,
|
||||
"prev_txid" BLOB NOT NULL,
|
||||
"register_height" INTEGER NOT NULL,
|
||||
"owner_id" INTEGER NOT NULL REFERENCES "owner" ("id")
|
||||
"owner_id" INTEGER NOT NULL REFERENCES "owner" ("id"),
|
||||
"backup_owner_id" INTEGER REFERENCES "owner" ("id")
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "name_hash_type_id" ON mappings("name_hash", "type");
|
||||
)";
|
||||
|
@ -1003,17 +1024,39 @@ bool name_system_db::init(cryptonote::network_type nettype, sqlite3 *db, uint64_
|
|||
this->db = db;
|
||||
this->nettype = nettype;
|
||||
|
||||
char constexpr GET_MAPPINGS_BY_OWNER_SQL[] = R"(SELECT * FROM "mappings" JOIN "owner" ON "mappings"."owner_id" = "owner"."id" WHERE "public_key" = ?)";
|
||||
char constexpr GET_MAPPINGS_ON_HEIGHT_AND_NEWER_SQL[] = R"(SELECT * FROM "mappings" JOIN "owner" on "mappings"."owner_id" = "owner"."id" WHERE "register_height" >= ?)";
|
||||
char constexpr GET_MAPPING_SQL[] = R"(SELECT * FROM "mappings" JOIN "owner" on "mappings"."owner_id" = "owner"."id" WHERE "type" = ? AND "name_hash" = ?)";
|
||||
char constexpr GET_OWNER_BY_ID_SQL[] = R"(SELECT * FROM "owner" WHERE "id" = ?)";
|
||||
char constexpr GET_OWNER_BY_KEY_SQL[] = R"(SELECT * FROM "owner" WHERE "public_key" = ?)";
|
||||
char constexpr GET_SETTINGS_SQL[] = R"(SELECT * FROM "settings" WHERE "id" = 1)";
|
||||
char constexpr PRUNE_MAPPINGS_SQL[] = R"(DELETE FROM "mappings" WHERE "register_height" >= ?)";
|
||||
char constexpr PRUNE_OWNERS_SQL[] = R"(DELETE FROM "owner" WHERE "id" NOT IN (SELECT "owner_id" FROM "mappings"))";
|
||||
char constexpr SAVE_MAPPING_SQL[] = R"(INSERT OR REPLACE INTO "mappings" ("type", "name_hash", "encrypted_value", "txid", "prev_txid", "register_height", "owner_id") VALUES (?,?,?,?,?,?,?))";
|
||||
char constexpr SAVE_OWNER_SQL[] = R"(INSERT INTO "owner" ("public_key") VALUES (?);)";
|
||||
char constexpr SAVE_SETTINGS_SQL[] = R"(INSERT OR REPLACE INTO "settings" ("id", "top_height", "top_hash", "version") VALUES (1,?,?,?))";
|
||||
char constexpr GET_MAPPINGS_BY_OWNER_SQL[] =
|
||||
R"(SELECT "mappings".*, "o1"."public_key", "o2"."public_key" FROM "mappings"
|
||||
JOIN "owner" "o1" ON "mappings"."owner_id" = "o1"."id"
|
||||
LEFT JOIN "owner" "o2" ON "mappings"."backup_owner_id" = "o2"."id"
|
||||
WHERE "o1"."public_key" = ? OR "o2"."public_key" = ?)";
|
||||
|
||||
char constexpr GET_MAPPINGS_ON_HEIGHT_AND_NEWER_SQL[] =
|
||||
R"(SELECT "mappings".*, "o1"."public_key", "o2"."public_key" FROM "mappings"
|
||||
JOIN "owner" "o1" ON "mappings"."owner_id" = "o1"."id"
|
||||
LEFT JOIN "owner" "o2" ON "mappings"."backup_owner_id" = "o2"."id"
|
||||
WHERE "register_height" >= ?)";
|
||||
|
||||
char constexpr GET_MAPPING_SQL[] =
|
||||
R"(SELECT "mappings".*, "o1"."public_key", "o2"."public_key" FROM "mappings"
|
||||
JOIN "owner" "o1" ON "mappings"."owner_id" = "o1"."id"
|
||||
LEFT JOIN "owner" "o2" ON "mappings"."backup_owner_id" = "o2"."id"
|
||||
WHERE "type" = ? AND "name" = ?)";
|
||||
|
||||
char constexpr GET_OWNER_BY_ID_SQL[] = R"(SELECT * FROM "owner" WHERE "id" = ?)";
|
||||
char constexpr GET_OWNER_BY_KEY_SQL[] = R"(SELECT * FROM "owner" WHERE "public_key" = ?)";
|
||||
char constexpr GET_SETTINGS_SQL[] = R"(SELECT * FROM "settings" WHERE "id" = 1)";
|
||||
char constexpr PRUNE_MAPPINGS_SQL[] = R"(DELETE FROM "mappings" WHERE "register_height" >= ?)";
|
||||
|
||||
char constexpr PRUNE_OWNERS_SQL[] =
|
||||
R"(DELETE FROM "owner"
|
||||
WHERE NOT EXISTS
|
||||
(SELECT * FROM "mappings"
|
||||
WHERE "owner"."id" = "mappings"."owner_id"
|
||||
OR "owner"."id" = "mappings"."backup_owner_id"))";
|
||||
|
||||
char constexpr SAVE_MAPPING_SQL[] = R"(INSERT OR REPLACE INTO "mappings" ("type", "name", "value", "txid", "prev_txid", "register_height", "owner_id", "backup_owner_id") VALUES (?,?,?,?,?,?,?,?))";
|
||||
char constexpr SAVE_OWNER_SQL[] = R"(INSERT INTO "owner" ("public_key") VALUES (?);)";
|
||||
char constexpr SAVE_SETTINGS_SQL[] = R"(INSERT OR REPLACE INTO "settings" ("id", "top_height", "top_hash", "version") VALUES (1,?,?,?))";
|
||||
|
||||
sqlite3_stmt *test;
|
||||
|
||||
|
@ -1106,27 +1149,49 @@ scoped_db_transaction::~scoped_db_transaction()
|
|||
lns_db.transaction_begun = false;
|
||||
}
|
||||
|
||||
static bool add_lns_entry(lns::name_system_db &lns_db, uint64_t height, cryptonote::tx_extra_loki_name_system const &entry, crypto::hash const &tx_hash)
|
||||
static int64_t add_or_get_owner_id(lns::name_system_db &lns_db, crypto::hash const &tx_hash, cryptonote::tx_extra_loki_name_system const &entry, crypto::generic_public_key const &key)
|
||||
{
|
||||
int64_t owner_id = 0;
|
||||
if (owner_record owner = lns_db.get_owner_by_key(entry.owner)) owner_id = owner.id;
|
||||
if (owner_id == 0)
|
||||
int64_t result = 0;
|
||||
if (owner_record owner = lns_db.get_owner_by_key(key)) result = owner.id;
|
||||
if (result == 0)
|
||||
{
|
||||
if (entry.command == lns::tx_command::update)
|
||||
{
|
||||
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 false;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!lns_db.save_owner(entry.owner, &owner_id))
|
||||
if (!lns_db.save_owner(key, &result))
|
||||
{
|
||||
LOG_PRINT_L1("Failed to save LNS owner to DB tx: " << tx_hash << ", type: " << entry.type << ", name_hash: " << entry.name_hash << ", owner: " << entry.owner);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool add_lns_entry(lns::name_system_db &lns_db, uint64_t height, cryptonote::tx_extra_loki_name_system const &entry, crypto::hash const &tx_hash)
|
||||
{
|
||||
int64_t owner_id = add_or_get_owner_id(lns_db, tx_hash, entry, entry.owner);
|
||||
if (owner_id == 0)
|
||||
{
|
||||
assert(owner_id != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t backup_owner_id = 0;
|
||||
if (entry.backup_owner)
|
||||
{
|
||||
backup_owner_id = add_or_get_owner_id(lns_db, tx_hash, entry, entry.backup_owner);
|
||||
if (backup_owner_id == 0)
|
||||
{
|
||||
assert(backup_owner_id != 0);
|
||||
LOG_PRINT_L1("Failed to save LNS backup owner to DB tx: " << tx_hash << ", type: " << entry.type << ", name_hash: " << entry.name_hash << ", owner: " << entry.owner);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
assert(owner_id != 0);
|
||||
|
||||
if (!lns_db.save_mapping(tx_hash, entry, height, owner_id))
|
||||
if (!lns_db.save_mapping(tx_hash, entry, height, owner_id, backup_owner_id))
|
||||
{
|
||||
LOG_PRINT_L1("Failed to save LNS entry to DB tx: " << tx_hash << ", type: " << entry.type << ", name_hash: " << entry.name_hash << ", owner: " << entry.owner);
|
||||
return false;
|
||||
|
@ -1276,7 +1341,7 @@ bool name_system_db::save_owner(crypto::generic_public_key const &key, int64_t *
|
|||
return result;
|
||||
}
|
||||
|
||||
bool name_system_db::save_mapping(crypto::hash const &tx_hash, cryptonote::tx_extra_loki_name_system const &src, uint64_t height, int64_t owner_id)
|
||||
bool name_system_db::save_mapping(crypto::hash const &tx_hash, cryptonote::tx_extra_loki_name_system const &src, uint64_t height, int64_t owner_id, int64_t backup_owner_id)
|
||||
{
|
||||
std::string name_hash = hash_to_base64(src.name_hash);
|
||||
sqlite3_stmt *statement = save_mapping_sql;
|
||||
|
@ -1287,6 +1352,10 @@ bool name_system_db::save_mapping(crypto::hash const &tx_hash, cryptonote::tx_ex
|
|||
sqlite3_bind_blob (statement, static_cast<int>(mapping_record_row::prev_txid), src.prev_txid.data, sizeof(src.prev_txid), nullptr /*destructor*/);
|
||||
sqlite3_bind_int64(statement, static_cast<int>(mapping_record_row::register_height), static_cast<int64_t>(height));
|
||||
sqlite3_bind_int64(statement, static_cast<int>(mapping_record_row::owner_id), owner_id);
|
||||
if (backup_owner_id != 0)
|
||||
{
|
||||
sqlite3_bind_int64(statement, static_cast<int>(mapping_record_row::backup_owner_id), backup_owner_id);
|
||||
}
|
||||
bool result = sql_run_statement(nettype, lns_sql_type::save_mapping, statement, nullptr);
|
||||
return result;
|
||||
}
|
||||
|
@ -1358,7 +1427,11 @@ std::vector<mapping_record> name_system_db::get_mappings(std::vector<uint16_t> c
|
|||
|
||||
if (types.size())
|
||||
{
|
||||
char constexpr SQL_PREFIX[] = R"(SELECT * FROM "mappings" JOIN "owner" ON "mappings"."owner_id" = "owner"."id" WHERE "name_hash" = ? AND "type" in ()";
|
||||
char constexpr SQL_PREFIX[] =
|
||||
R"(SELECT "mappings".*, "o1"."public_key", "o2"."public_key" FROM "mappings"
|
||||
JOIN "owner" "o1" ON "mappings"."owner_id" = "o1"."id"
|
||||
LEFT JOIN "owner" "o2" ON "mappings"."backup_owner_id" = "o2"."id"
|
||||
WHERE "name" = ? AND "type" in ()";
|
||||
char constexpr SQL_SUFFIX[] = R"())";
|
||||
|
||||
std::stringstream stream;
|
||||
|
@ -1399,7 +1472,12 @@ std::vector<mapping_record> name_system_db::get_mappings_by_owners(std::vector<c
|
|||
std::string sql_statement;
|
||||
// Generate string statement
|
||||
{
|
||||
char constexpr SQL_PREFIX[] = R"(SELECT * FROM "mappings" JOIN "owner" ON "mappings"."owner_id" = "owner"."id" WHERE "public_key" in ()";
|
||||
char constexpr SQL_PREFIX[] =
|
||||
R"(SELECT "mappings".*, "o1"."public_key", "o2"."public_key" FROM "mappings"
|
||||
JOIN "owner" "o1" ON "mappings"."owner_id" = "o1"."id"
|
||||
LEFT JOIN "owner" "o2" ON "mappings"."backup_owner_id" = "o2"."id"
|
||||
WHERE "o1"."public_key" in ()";
|
||||
char constexpr SQL_MIDDLE[] = R"(OR "o2"."public_key" in ()";
|
||||
char constexpr SQL_SUFFIX[] = R"())";
|
||||
|
||||
std::stringstream stream;
|
||||
|
@ -1410,6 +1488,14 @@ std::vector<mapping_record> name_system_db::get_mappings_by_owners(std::vector<c
|
|||
if (i < (keys.size() - 1)) stream << ", ";
|
||||
}
|
||||
stream << SQL_SUFFIX;
|
||||
|
||||
stream << SQL_MIDDLE;
|
||||
for (size_t i = 0; i < keys.size(); i++)
|
||||
{
|
||||
stream << "?";
|
||||
if (i < (keys.size() - 1)) stream << ", ";
|
||||
}
|
||||
stream << SQL_SUFFIX;
|
||||
sql_statement = stream.str();
|
||||
}
|
||||
|
||||
|
@ -1421,9 +1507,14 @@ std::vector<mapping_record> name_system_db::get_mappings_by_owners(std::vector<c
|
|||
|
||||
// Bind parameters statements
|
||||
int sql_param_index = 1;
|
||||
for (auto const &key : keys)
|
||||
sqlite3_bind_blob(statement, sql_param_index++, key.data, sizeof(key), nullptr /*destructor*/);
|
||||
assert((sql_param_index - 1) == static_cast<int>(keys.size()));
|
||||
for (size_t i = 0; i < keys.size(); i++)
|
||||
{
|
||||
for (auto const &key : keys)
|
||||
{
|
||||
sqlite3_bind_blob(statement, sql_param_index++, key.data, sizeof(key), nullptr /*destructor*/);
|
||||
}
|
||||
}
|
||||
assert((sql_param_index - 1) == (static_cast<int>(keys.size() * 2)));
|
||||
|
||||
// Execute
|
||||
sql_run_statement(nettype, lns_sql_type::get_mappings_by_owners, statement, &result);
|
||||
|
@ -1436,6 +1527,7 @@ std::vector<mapping_record> name_system_db::get_mappings_by_owner(crypto::generi
|
|||
sqlite3_stmt *statement = get_mappings_by_owner_sql;
|
||||
sqlite3_clear_bindings(statement);
|
||||
sqlite3_bind_blob(statement, 1 /*sql param index*/, key.data, sizeof(key), nullptr /*destructor*/);
|
||||
sqlite3_bind_blob(statement, 2 /*sql param index*/, key.data, sizeof(key), nullptr /*destructor*/);
|
||||
sql_run_statement(nettype, lns_sql_type::get_mappings_by_owner, statement, &result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -123,12 +123,12 @@ struct mapping_record
|
|||
std::string name_hash; // name hashed and represented in base64 encoding
|
||||
mapping_value encrypted_value;
|
||||
uint64_t register_height;
|
||||
int64_t owner_id;
|
||||
crypto::generic_public_key owner;
|
||||
crypto::generic_public_key backup_owner;
|
||||
int64_t backup_owner_id;
|
||||
crypto::hash txid;
|
||||
crypto::hash prev_txid;
|
||||
int64_t owner_id;
|
||||
int64_t backup_owner_id;
|
||||
crypto::generic_public_key owner;
|
||||
crypto::generic_public_key backup_owner;
|
||||
};
|
||||
|
||||
struct name_system_db
|
||||
|
@ -142,7 +142,7 @@ struct name_system_db
|
|||
// Signifies the blockchain has reorganized commences the rollback and pruning procedures.
|
||||
void block_detach(cryptonote::Blockchain const &blockchain, uint64_t new_blockchain_height);
|
||||
bool save_owner (crypto::generic_public_key const &key, int64_t *row_id);
|
||||
bool save_mapping (crypto::hash const &tx_hash, cryptonote::tx_extra_loki_name_system const &src, uint64_t height, int64_t owner_id);
|
||||
bool save_mapping (crypto::hash const &tx_hash, cryptonote::tx_extra_loki_name_system const &src, uint64_t height, int64_t owner_id, int64_t backup_owner_id = 0);
|
||||
bool save_settings (uint64_t top_height, crypto::hash const &top_hash, int version);
|
||||
|
||||
// Delete all mappings that are registered on height or newer followed by deleting all owners no longer referenced in the DB
|
||||
|
|
|
@ -288,9 +288,10 @@ loki_chain_generator::create_and_add_loki_name_system_tx(cryptonote::account_bas
|
|||
lns::mapping_value const &value,
|
||||
std::string const &name,
|
||||
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);
|
||||
cryptonote::transaction t = create_loki_name_system_tx(src, type, value, name, owner, backup_owner);
|
||||
add_tx(t, true /*can_be_added_to_blockchain*/, ""/*fail_msg*/, kept_by_block);
|
||||
return t;
|
||||
}
|
||||
|
@ -300,9 +301,10 @@ loki_chain_generator::create_and_add_loki_name_system_tx_update(cryptonote::acco
|
|||
lns::mapping_type type,
|
||||
lns::mapping_value const &value,
|
||||
std::string const &name,
|
||||
crypto::generic_signature *signature,
|
||||
bool kept_by_block)
|
||||
{
|
||||
cryptonote::transaction t = create_loki_name_system_tx_update(src, type, value, name);
|
||||
cryptonote::transaction t = create_loki_name_system_tx_update(src, type, value, name, signature);
|
||||
add_tx(t, true /*can_be_added_to_blockchain*/, ""/*fail_msg*/, kept_by_block);
|
||||
return t;
|
||||
}
|
||||
|
@ -518,6 +520,7 @@ cryptonote::transaction loki_chain_generator::create_loki_name_system_tx(crypton
|
|||
lns::mapping_value const &value,
|
||||
std::string const &name,
|
||||
crypto::generic_public_key const *owner,
|
||||
crypto::generic_public_key const *backup_owner,
|
||||
uint64_t burn) const
|
||||
{
|
||||
crypto::generic_public_key pkey;
|
||||
|
@ -547,7 +550,7 @@ cryptonote::transaction loki_chain_generator::create_loki_name_system_tx(crypton
|
|||
assert(encrypted);
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
cryptonote::tx_extra_loki_name_system data = cryptonote::tx_extra_loki_name_system::make_buy(pkey, nullptr, type, name_hash, encrypted_value.to_string(), prev_txid);
|
||||
cryptonote::tx_extra_loki_name_system data = cryptonote::tx_extra_loki_name_system::make_buy(pkey, backup_owner, type, name_hash, encrypted_value.to_string(), prev_txid);
|
||||
cryptonote::add_loki_name_system_to_tx_extra(extra, data);
|
||||
cryptonote::add_burned_amount_to_tx_extra(extra, burn);
|
||||
cryptonote::transaction result = {};
|
||||
|
|
|
@ -1421,9 +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.
|
||||
// value: The binary representation of the value part in the name->value mapping
|
||||
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, 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, bool kept_by_block = false);
|
||||
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_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);
|
||||
|
@ -1444,7 +1443,7 @@ 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, uint64_t burn = LNS_AUTO_BURN) const;
|
||||
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_update_w_extra(cryptonote::account_base const &src, cryptonote::tx_extra_loki_name_system const &lns_extra) const;
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(loki_name_system_name_value_max_lengths);
|
||||
GENERATE_AND_PLAY(loki_name_system_update_mapping_after_expiry_fails);
|
||||
GENERATE_AND_PLAY(loki_name_system_update_mapping);
|
||||
GENERATE_AND_PLAY(loki_name_system_update_mapping_multiple_owners);
|
||||
GENERATE_AND_PLAY(loki_name_system_update_mapping_non_existent_name_fails);
|
||||
GENERATE_AND_PLAY(loki_name_system_update_mapping_invalid_signature);
|
||||
GENERATE_AND_PLAY(loki_name_system_update_mapping_replay);
|
||||
|
|
|
@ -1176,9 +1176,9 @@ bool loki_name_system_get_mappings_by_owner::generate(std::vector<test_event_ent
|
|||
uint64_t wallet_height = gen.height();
|
||||
|
||||
loki_register_callback(events, "check_lns_entries", [&events, bob_key,
|
||||
wallet_height, wallet_name1, wallet_name2,
|
||||
session_height, session_name1, session_name2,
|
||||
lokinet_height, lokinet_name1, lokinet_name2
|
||||
wallet_height, wallet_name1, wallet_name2,
|
||||
session_height, session_name1, session_name2,
|
||||
lokinet_height, lokinet_name1, lokinet_name2
|
||||
](cryptonote::core &c, size_t ev_index)
|
||||
{
|
||||
DEFINE_TESTS_ERROR_CONTEXT("check_lns_entries");
|
||||
|
@ -2147,6 +2147,191 @@ bool loki_name_system_update_mapping::generate(std::vector<test_event_entry> &ev
|
|||
return true;
|
||||
}
|
||||
|
||||
bool loki_name_system_update_mapping_multiple_owners::generate(std::vector<test_event_entry>& events)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
|
||||
loki_chain_generator gen(events, hard_forks);
|
||||
gen.add_blocks_until_version(hard_forks.back().first);
|
||||
gen.add_n_blocks(10); /// generate some outputs and unlock them
|
||||
gen.add_mined_money_unlock_blocks();
|
||||
|
||||
cryptonote::account_base miner = gen.first_miner_;
|
||||
lns_keys_t miner_key = make_lns_keys(miner);
|
||||
|
||||
// Test 2 ed keys as owner
|
||||
{
|
||||
crypto::hash prev_txid = crypto::null_hash;
|
||||
crypto::generic_public_key owner1;
|
||||
crypto::generic_public_key owner2;
|
||||
crypto::ed25519_secret_key owner1_key;
|
||||
crypto::ed25519_secret_key owner2_key;
|
||||
|
||||
crypto_sign_ed25519_keypair(owner1.data, owner1_key.data);
|
||||
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);
|
||||
gen.create_and_add_next_block({tx1});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx1);
|
||||
|
||||
// Update with owner1
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
|
||||
// Update with owner2
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 2 monero keys as owner
|
||||
{
|
||||
crypto::hash prev_txid = crypto::null_hash;
|
||||
crypto::generic_public_key owner1;
|
||||
crypto::generic_public_key owner2;
|
||||
crypto::secret_key owner1_key;
|
||||
crypto::secret_key owner2_key;
|
||||
|
||||
crypto::generate_keys(owner1.monero, owner1_key);
|
||||
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);
|
||||
gen.create_and_add_next_block({tx1});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx1);
|
||||
|
||||
// Update with owner1
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
|
||||
// Update with owner2
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 1 ed/1 monero as owner
|
||||
{
|
||||
crypto::hash prev_txid = crypto::null_hash;
|
||||
crypto::generic_public_key owner1;
|
||||
crypto::generic_public_key owner2;
|
||||
crypto::ed25519_secret_key owner1_key;
|
||||
crypto::secret_key owner2_key;
|
||||
|
||||
crypto_sign_ed25519_keypair(owner1.data, owner1_key.data);
|
||||
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);
|
||||
gen.create_and_add_next_block({tx1});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx1);
|
||||
|
||||
// Update with owner1
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
|
||||
// Update with owner2
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 1 monero/1 ed as owner
|
||||
{
|
||||
crypto::hash prev_txid = crypto::null_hash;
|
||||
crypto::generic_public_key owner1;
|
||||
crypto::generic_public_key owner2;
|
||||
crypto::secret_key owner1_key;
|
||||
crypto::ed25519_secret_key owner2_key;
|
||||
|
||||
crypto::generate_keys(owner1.monero, owner1_key);
|
||||
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);
|
||||
gen.create_and_add_next_block({tx1});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx1);
|
||||
|
||||
// Update with owner1
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
|
||||
// Update with owner2
|
||||
{
|
||||
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(), prev_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);
|
||||
gen.create_and_add_next_block({tx2});
|
||||
prev_txid = cryptonote::get_transaction_hash(tx2);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loki_name_system_update_mapping_non_existent_name_fails::generate(std::vector<test_event_entry> &events)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
|
||||
|
@ -2282,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*/, burn);
|
||||
cryptonote::transaction tx = gen.create_loki_name_system_tx(miner, type, value, name, 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*/);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ struct loki_name_system_name_renewal
|
|||
struct loki_name_system_name_value_max_lengths : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_update_mapping_after_expiry_fails : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_update_mapping : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_update_mapping_multiple_owners : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_update_mapping_non_existent_name_fails : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_update_mapping_invalid_signature : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
struct loki_name_system_update_mapping_replay : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
|
||||
|
|
Loading…
Reference in New Issue