townforge/tests/db_tests/db_tests_cc.cpp
Crypto City d079502b34 deactivate active flags which have just changed owner
to avoid an exploit with keeping placeholders accounts with
different occupations and shuffling flags around at the right
times to get all bonuses
2024-03-11 14:51:45 +00:00

1398 lines
52 KiB
C++

// Copyright (c) 2020, Crypto City
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "blockchain_db/blockchain_db.h"
#include "cc/cc.h"
#include "cc/cc_script.h"
#include "cc/coru.h"
#include "db_tests.h"
bool db_tests_cc_blobs(cryptonote::BlockchainDB &db)
{
const crypto::hash hash = cc::script::get_blob_hash("test");
size_t n_blobs;
cryptonote::blobdata blob;
n_blobs = 0;
DB_TESTS_ASSERT(db.for_all_cc_blobs([&n_blobs](const crypto::hash&, uint32_t, const cryptonote::blobdata_ref&) { ++n_blobs; return true; }));
DB_TESTS_ASSERT(n_blobs == 0);
DB_TESTS_ASSERT(db.get_cc_blob(hash, blob) == 0);
db.add_cc_blob("test");
n_blobs = 0;
DB_TESTS_ASSERT(db.for_all_cc_blobs([&n_blobs, &hash](const crypto::hash &h, uint32_t refs, const cryptonote::blobdata_ref &blob) {
DB_TESTS_ASSERT(h == hash);
DB_TESTS_ASSERT(refs == 1);
DB_TESTS_ASSERT(blob == "test");
++n_blobs;
return true;
}));
DB_TESTS_ASSERT(n_blobs == 1);
DB_TESTS_ASSERT(db.get_cc_blob(hash, blob) == 1);
DB_TESTS_ASSERT(blob == "test");
db.add_cc_blob("test");
n_blobs = 0;
DB_TESTS_ASSERT(db.for_all_cc_blobs([&n_blobs, &hash](const crypto::hash &h, uint32_t refs, const cryptonote::blobdata_ref &blob) {
DB_TESTS_ASSERT(h == hash);
DB_TESTS_ASSERT(refs == 2);
DB_TESTS_ASSERT(blob == "test");
++n_blobs;
return true;
}));
DB_TESTS_ASSERT(n_blobs == 1);
DB_TESTS_ASSERT(db.get_cc_blob(hash, blob) == 2);
DB_TESTS_ASSERT(blob == "test");
db.delete_cc_blob("test");
n_blobs = 0;
DB_TESTS_ASSERT(db.for_all_cc_blobs([&n_blobs, &hash](const crypto::hash &h, uint32_t refs, const cryptonote::blobdata_ref &blob) {
DB_TESTS_ASSERT(h == hash);
DB_TESTS_ASSERT(refs == 1);
DB_TESTS_ASSERT(blob == "test");
++n_blobs;
return true;
}));
DB_TESTS_ASSERT(n_blobs == 1);
DB_TESTS_ASSERT(db.get_cc_blob(hash, blob) == 1);
DB_TESTS_ASSERT(blob == "test");
db.delete_cc_blob("test");
n_blobs = 0;
DB_TESTS_ASSERT(db.for_all_cc_blobs([&n_blobs](const crypto::hash&, uint32_t, const cryptonote::blobdata_ref&) { ++n_blobs; return true; }));
DB_TESTS_ASSERT(n_blobs == 0);
DB_TESTS_ASSERT(db.get_cc_blob(hash, blob) == 0);
return true;
}
bool db_tests_cc_random_seed(cryptonote::BlockchainDB &db)
{
db.set_cc_random_seed(crypto::null_hash);
DB_TESTS_ASSERT(db.get_cc_random_seed() == crypto::null_hash);
crypto::hash seed = crypto::null_hash;
seed.data[3] = 0x42;
db.set_cc_random_seed(seed);
DB_TESTS_ASSERT(db.get_cc_random_seed() == seed);
return true;
}
bool db_tests_cc_foreclosures(cryptonote::BlockchainDB &db)
{
size_t n_mortgages = 0;
DB_TESTS_ASSERT(db.for_all_cc_foreclosures([&n_mortgages](const cc::foreclosure_t&) {
++n_mortgages;
return true;
}));
DB_TESTS_ASSERT(n_mortgages == 0);
db.add_cc_foreclosure({10, 11, 12, 13});
n_mortgages = 0;
DB_TESTS_ASSERT(db.for_all_cc_foreclosures([&n_mortgages](const cc::foreclosure_t &foreclosure) {
DB_TESTS_ASSERT(foreclosure.mortgage == 10);
DB_TESTS_ASSERT(foreclosure.flag == 11);
DB_TESTS_ASSERT(foreclosure.height == 12);
DB_TESTS_ASSERT(foreclosure.debt_per_share == 13);
++n_mortgages;
return true;
}));
DB_TESTS_ASSERT(n_mortgages == 1);
db.remove_cc_foreclosure(10);
n_mortgages = 0;
DB_TESTS_ASSERT(db.for_all_cc_foreclosures([&n_mortgages](const cc::foreclosure_t&) {
++n_mortgages;
return true;
}));
DB_TESTS_ASSERT(n_mortgages == 0);
return true;
}
bool db_tests_cc_runestones(cryptonote::BlockchainDB &db)
{
size_t n_runestones = 0;
DB_TESTS_ASSERT(db.for_all_cc_runestones([&n_runestones](const cc::runestone_t &runestone) {
++n_runestones;
return true;
}));
DB_TESTS_ASSERT(n_runestones == 0);
cc::runestone_t runestone;
runestone.flag = 10;
runestone.x = 11;
runestone.y = 12;
runestone.h = 13;
runestone.script = 14;
runestone.message = "15";
runestone.overrides.push_back(std::make_tuple(0, 1, "foo"));
runestone.overrides.push_back(std::make_tuple(1, 2, "bar"));
db.add_cc_runestone(runestone);
n_runestones = 0;
DB_TESTS_ASSERT(db.for_all_cc_runestones([&n_runestones](const cc::runestone_t &runestone) {
DB_TESTS_ASSERT(runestone.flag == 10);
DB_TESTS_ASSERT(runestone.x == 11);
DB_TESTS_ASSERT(runestone.y == 12);
DB_TESTS_ASSERT(runestone.h == 13);
DB_TESTS_ASSERT(runestone.script == 14);
DB_TESTS_ASSERT(runestone.message == "15");
DB_TESTS_ASSERT(runestone.overrides.size() == 2);
DB_TESTS_ASSERT(runestone.overrides[0] == std::make_tuple(0, 1, "foo"));
DB_TESTS_ASSERT(runestone.overrides[1] == std::make_tuple(1, 2, "bar"));
++n_runestones;
return true;
}));
DB_TESTS_ASSERT(n_runestones == 1);
cc::runestone_t r;
DB_TESTS_ASSERT(!db.get_cc_runestone(10, 0, 0, 0, r));
DB_TESTS_ASSERT(db.get_cc_runestone(10, 11, 12, 13, r));
DB_TESTS_ASSERT(r.flag == 10);
DB_TESTS_ASSERT(r.x == 11);
DB_TESTS_ASSERT(r.y == 12);
DB_TESTS_ASSERT(r.h == 13);
DB_TESTS_ASSERT(r.script == 14);
DB_TESTS_ASSERT(r.message == "15");
DB_TESTS_ASSERT(r.overrides.size() == 2);
DB_TESTS_ASSERT(r.overrides[0] == std::make_tuple(0, 1, "foo"));
DB_TESTS_ASSERT(r.overrides[1] == std::make_tuple(1, 2, "bar"));
db.remove_cc_runestone(10, 11, 12, 13);
n_runestones = 0;
DB_TESTS_ASSERT(db.for_all_cc_runestones([&n_runestones](const cc::runestone_t &runestone) {
++n_runestones;
return true;
}));
DB_TESTS_ASSERT(n_runestones == 0);
return true;
}
bool db_tests_cc_script_variables(cryptonote::BlockchainDB &db)
{
size_t n_script_variables = 0;
DB_TESTS_ASSERT(db.for_all_cc_script_variables([&n_script_variables](const boost::string_ref&, uint64_t) { ++n_script_variables; return true; }));
DB_TESTS_ASSERT(n_script_variables == 0);
DB_TESTS_ASSERT(db.get_cc_script_variable("test") == 0);
db.set_cc_script_variable("test", 1);
DB_TESTS_ASSERT(db.get_cc_script_variable("test") == 1);
n_script_variables = 0;
DB_TESTS_ASSERT(db.for_all_cc_script_variables([&n_script_variables](const boost::string_ref &name, uint64_t value) {
DB_TESTS_ASSERT(name == "test");
DB_TESTS_ASSERT(value == 1);
++n_script_variables;
return true;
}));
DB_TESTS_ASSERT(n_script_variables == 1);
db.set_cc_script_variable("test", 0);
DB_TESTS_ASSERT(db.get_cc_script_variable("test") == 0);
n_script_variables = 0;
DB_TESTS_ASSERT(db.for_all_cc_script_variables([&n_script_variables](const boost::string_ref&, uint64_t) { ++n_script_variables; return true; }));
DB_TESTS_ASSERT(n_script_variables == 0);
return true;
}
bool db_tests_cc_scripts(cryptonote::BlockchainDB &db)
{
size_t n_scripts = 0;
DB_TESTS_ASSERT(db.for_all_cc_scripts([&n_scripts](const cryptonote::cc_script_data_t&){ ++n_scripts; return true; }));
DB_TESTS_ASSERT(n_scripts == 0);
DB_TESTS_ASSERT(db.get_num_cc_scripts() == 0);
const uint32_t id = db.allocate_new_cc_script("name", "icon", "desc", "blob", false, 42, true, false);
DB_TESTS_ASSERT(id != 0);
DB_TESTS_ASSERT(db.get_num_cc_scripts() == 1);
n_scripts = 0;
DB_TESTS_ASSERT(db.for_all_cc_scripts([&n_scripts, id](const cryptonote::cc_script_data_t &s){
DB_TESTS_ASSERT(s.id == id);
DB_TESTS_ASSERT(s.name == "name");
DB_TESTS_ASSERT(s.desc == "desc");
DB_TESTS_ASSERT(s.icon == "icon");
DB_TESTS_ASSERT(s.blob == "blob");
DB_TESTS_ASSERT(s.owner == 42);
DB_TESTS_ASSERT(s.is_public == true);
DB_TESTS_ASSERT(s.enabled == true);
DB_TESTS_ASSERT(s.is_storyline == false);
++n_scripts;
return true;
}));
DB_TESTS_ASSERT(n_scripts == 1);
const uint32_t id2 = db.allocate_new_cc_script("name2", "icon2", "desc2", "blob2", false, 43, false, true);
DB_TESTS_ASSERT(id2 && id2 == id + 1);
n_scripts = 0;
DB_TESTS_ASSERT(db.for_all_cc_scripts([&n_scripts, id](const cryptonote::cc_script_data_t &s){
DB_TESTS_ASSERT(s.id == id || s.id == id + 1);
DB_TESTS_ASSERT(s.name == (s.id == id ? "name" : "name2"));
DB_TESTS_ASSERT(s.desc == (s.id == id ? "desc" : "desc2"));
DB_TESTS_ASSERT(s.icon == (s.id == id ? "icon" : "icon2"));
DB_TESTS_ASSERT(s.blob == (s.id == id ? "blob" : "blob2"));
DB_TESTS_ASSERT(s.owner == (s.id == id ? 42 : 43));
DB_TESTS_ASSERT(s.is_public == (s.id == id));
DB_TESTS_ASSERT(s.enabled);
DB_TESTS_ASSERT(s.is_storyline == (s.id != id));
++n_scripts;
return true;
}));
DB_TESTS_ASSERT(n_scripts == 2);
DB_TESTS_ASSERT(db.get_num_cc_scripts() == 2);
cryptonote::cc_script_data_t sd;
DB_TESTS_ASSERT(db.get_cc_script_data(id, sd));
DB_TESTS_ASSERT(sd.id == id);
DB_TESTS_ASSERT(sd.name == "name");
DB_TESTS_ASSERT(db.get_cc_script_data(id2, sd));
DB_TESTS_ASSERT(sd.id == id2);
DB_TESTS_ASSERT(sd.name == "name2");
db.set_cc_script_enabled(id, false);
n_scripts = 0;
DB_TESTS_ASSERT(db.for_all_cc_scripts([&n_scripts, id](const cryptonote::cc_script_data_t &s){
DB_TESTS_ASSERT(s.enabled == (s.id != id));
++n_scripts;
return true;
}));
DB_TESTS_ASSERT(n_scripts == 2);
db.set_cc_script_enabled(id, true);
n_scripts = 0;
DB_TESTS_ASSERT(db.for_all_cc_scripts([&n_scripts, id](const cryptonote::cc_script_data_t &s){
DB_TESTS_ASSERT(s.enabled == true);
++n_scripts;
return true;
}));
DB_TESTS_ASSERT(n_scripts == 2);
db.delete_cc_script(id2);
n_scripts = 0;
DB_TESTS_ASSERT(db.for_all_cc_scripts([&n_scripts, id](const cryptonote::cc_script_data_t &s){
DB_TESTS_ASSERT(s.id == id);
DB_TESTS_ASSERT(s.name == "name");
DB_TESTS_ASSERT(s.desc == "desc");
DB_TESTS_ASSERT(s.icon == "icon");
DB_TESTS_ASSERT(s.blob == "blob");
DB_TESTS_ASSERT(s.owner == 42);
DB_TESTS_ASSERT(s.is_public == true);
++n_scripts;
return true;
}));
DB_TESTS_ASSERT(n_scripts == 1);
DB_TESTS_ASSERT(db.get_num_cc_scripts() == 1);
return true;
}
bool db_tests_cc_script_effects(cryptonote::BlockchainDB &db)
{
cc::script::script_effects_t effects;
DB_TESTS_EXCEPTION(db.get_last_cc_script_effects(effects));
cc::script::script_effects_t test_effects;
test_effects.balances.push_back({3, 4, 5});
test_effects.local_variables.push_back({"test", 6});
db.add_cc_script_effects(test_effects);
db.get_last_cc_script_effects(effects);
DB_TESTS_ASSERT(effects.balances.size() == 1 && effects.balances[0].account == 3 && effects.balances[0].counterparty == 4 && effects.balances[0].balance_delta == 5);
DB_TESTS_ASSERT(effects.local_variables.size() == 1 && effects.local_variables[0].name == "test" && effects.local_variables[0].value_delta == 6);
db.add_cc_script_effects(test_effects);
db.get_last_cc_script_effects(effects);
DB_TESTS_ASSERT(effects.balances.size() == 1 && effects.balances[0].account == 3 && effects.balances[0].counterparty == 4 && effects.balances[0].balance_delta == 5);
DB_TESTS_ASSERT(effects.local_variables.size() == 1 && effects.local_variables[0].name == "test" && effects.local_variables[0].value_delta == 6);
db.delete_last_cc_script_effects();
db.delete_last_cc_script_effects();
DB_TESTS_EXCEPTION(db.delete_last_cc_script_effects());
return true;
}
bool db_tests_cc_item_counts(cryptonote::BlockchainDB &db)
{
DB_TESTS_ASSERT(db.get_cc_item_count(1) == 0);
DB_TESTS_ASSERT(db.get_cc_item_count(2) == 0);
db.set_cc_item_count(1, 1);
db.set_cc_item_count(2, 2);
DB_TESTS_ASSERT(db.get_cc_item_count(1) == 1);
DB_TESTS_ASSERT(db.get_cc_item_count(2) == 2);
db.set_cc_item_count(1, 0);
db.set_cc_item_count(2, 0);
DB_TESTS_ASSERT(db.get_cc_item_count(1) == 0);
DB_TESTS_ASSERT(db.get_cc_item_count(2) == 0);
return true;
}
bool db_tests_cc_invitations(cryptonote::BlockchainDB &db)
{
crypto::public_key pkey0 = crypto::null_pkey, pkey1 = crypto::null_pkey;
pkey0.data[0] = 8;
pkey1.data[0] = 16;
DB_TESTS_ASSERT(!db.has_invitation(pkey0));
DB_TESTS_ASSERT(!db.has_invitation(pkey1));
db.add_invitation(pkey0);
DB_TESTS_ASSERT(db.has_invitation(pkey0));
DB_TESTS_ASSERT(!db.has_invitation(pkey1));
db.add_invitation(pkey1);
DB_TESTS_ASSERT(db.has_invitation(pkey0));
DB_TESTS_ASSERT(db.has_invitation(pkey1));
db.remove_invitation(pkey0);
DB_TESTS_ASSERT(!db.has_invitation(pkey0));
DB_TESTS_ASSERT(db.has_invitation(pkey1));
db.remove_invitation(pkey1);
DB_TESTS_ASSERT(!db.has_invitation(pkey0));
DB_TESTS_ASSERT(!db.has_invitation(pkey1));
return true;
}
bool db_tests_cc_attributes(cryptonote::BlockchainDB &db)
{
cryptonote::cc_attribute_data_t ad;
size_t n_attributes = 0;
DB_TESTS_ASSERT(db.for_all_cc_attributes([&n_attributes](const cryptonote::cc_attribute_data_t &ad){ ++n_attributes; return true; }));
DB_TESTS_ASSERT(n_attributes == 0);
DB_TESTS_ASSERT(!db.get_cc_attribute(0, ad));
DB_TESTS_ASSERT(!db.get_cc_attribute(1, ad));
DB_TESTS_EXCEPTION(db.delete_cc_attribute(0));
DB_TESTS_EXCEPTION(db.delete_cc_attribute(1));
const uint32_t id = db.allocate_new_cc_attribute("name", "desc");
DB_TESTS_ASSERT(id == 1);
n_attributes = 0;
DB_TESTS_ASSERT(db.for_all_cc_attributes([&n_attributes](const cryptonote::cc_attribute_data_t &ad){
DB_TESTS_ASSERT(ad.name == "name");
DB_TESTS_ASSERT(ad.description == "desc");
++n_attributes;
return true;
}));
DB_TESTS_ASSERT(n_attributes == 1);
DB_TESTS_ASSERT(!db.get_cc_attribute(0, ad));
DB_TESTS_ASSERT(db.get_cc_attribute(1, ad));
DB_TESTS_ASSERT(ad.name == "name");
DB_TESTS_ASSERT(ad.description == "desc");
db.delete_cc_attribute(id);
DB_TESTS_ASSERT(!db.get_cc_attribute(0, ad));
DB_TESTS_ASSERT(!db.get_cc_attribute(1, ad));
return true;
}
bool db_tests_cc_auctions(cryptonote::BlockchainDB &db)
{
cc::auction_t ad;
size_t n_auctions = 0;
DB_TESTS_ASSERT(db.for_all_cc_auctions([&n_auctions](const cc::auction_t &auction){ ++n_auctions; return true; }));
DB_TESTS_ASSERT(n_auctions == 0);
DB_TESTS_ASSERT(!db.get_cc_auction_data(0, ad));
DB_TESTS_ASSERT(!db.get_cc_auction_data(1, ad));
DB_TESTS_EXCEPTION(db.remove_cc_auction(0));
DB_TESTS_EXCEPTION(db.remove_cc_auction(1));
const uint32_t id = db.allocate_cc_auction(1, cc::auction_t::type_flag, {std::make_pair(1, 1)}, 2, true, 60, "a", "b", 0);
DB_TESTS_ASSERT(id == 1);
n_auctions = 0;
DB_TESTS_ASSERT(db.for_all_cc_auctions([&n_auctions](const cc::auction_t &ad){
DB_TESTS_ASSERT(ad.id == 1);
DB_TESTS_ASSERT(ad.seller == 1);
DB_TESTS_ASSERT(ad.type == cc::auction_t::type_flag);
DB_TESTS_ASSERT(ad.entries.size() == 1);
DB_TESTS_ASSERT(ad.entries[0].first == 1);
DB_TESTS_ASSERT(ad.entries[0].second == 1);
DB_TESTS_ASSERT(ad.reserve_price == 60);
DB_TESTS_ASSERT(ad.title == "a");
DB_TESTS_ASSERT(ad.description == "b");
DB_TESTS_ASSERT(ad.bids.empty());
++n_auctions;
return true;
}));
DB_TESTS_ASSERT(n_auctions == 1);
DB_TESTS_ASSERT(!db.get_cc_auction_data(0, ad));
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
DB_TESTS_ASSERT(ad.id == 1);
DB_TESTS_ASSERT(ad.seller == 1);
DB_TESTS_ASSERT(ad.type == cc::auction_t::type_flag);
DB_TESTS_ASSERT(ad.entries.size() == 1);
DB_TESTS_ASSERT(ad.entries[0].first == 1);
DB_TESTS_ASSERT(ad.entries[0].second == 1);
DB_TESTS_ASSERT(ad.bids.empty());
db.add_cc_auction_bid(1, 2, crypto::null_pkey, 200, 200);
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
DB_TESTS_ASSERT(ad.bids.size() == 1);
DB_TESTS_ASSERT(ad.bids[0] == std::make_tuple(2, crypto::null_pkey, 200, 200));
db.add_cc_auction_bid(1, 3, crypto::null_pkey, 400, 300);
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
DB_TESTS_ASSERT(ad.bids.size() == 2);
DB_TESTS_ASSERT(ad.bids[0] == std::make_tuple(2, crypto::null_pkey, 200, 200));
DB_TESTS_ASSERT(ad.bids[1] == std::make_tuple(3, crypto::null_pkey, 400, 300));
db.set_cc_auction_ended(1, true);
n_auctions = 0;
DB_TESTS_ASSERT(db.for_all_cc_auctions([&n_auctions](const cc::auction_t &auction){ ++n_auctions; return true; }));
DB_TESTS_ASSERT(n_auctions == 0);
DB_TESTS_ASSERT(!db.get_cc_auction_data(1, ad));
db.set_cc_auction_ended(1, false);
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
db.remove_last_cc_auction_bid(1);
db.remove_last_cc_auction_bid(1);
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
DB_TESTS_ASSERT(ad.bids.empty());
db.remove_cc_auction(1);
DB_TESTS_ASSERT(!db.get_cc_auction_data(0, ad));
DB_TESTS_ASSERT(!db.get_cc_auction_data(1, ad));
return true;
}
bool db_tests_cc_hunt(cryptonote::BlockchainDB &db)
{
uint32_t moose, bears;
DB_TESTS_EXCEPTION(db.get_last_cc_hunt(moose, bears));
DB_TESTS_EXCEPTION(db.remove_last_cc_hunt());
db.add_cc_hunt(123, 456);
db.get_last_cc_hunt(moose, bears);
DB_TESTS_ASSERT(moose == 123);
DB_TESTS_ASSERT(bears == 456);
db.add_cc_hunt(555, 888);
db.get_last_cc_hunt(moose, bears);
DB_TESTS_ASSERT(moose == 555);
DB_TESTS_ASSERT(bears == 888);
db.remove_last_cc_hunt();
db.get_last_cc_hunt(moose, bears);
DB_TESTS_ASSERT(moose == 123);
DB_TESTS_ASSERT(bears == 456);
db.remove_last_cc_hunt();
DB_TESTS_EXCEPTION(db.get_last_cc_hunt(moose, bears));
DB_TESTS_EXCEPTION(db.remove_last_cc_hunt());
db.add_cc_hunt(789, 111);
db.get_last_cc_hunt(moose, bears);
DB_TESTS_ASSERT(moose == 789);
DB_TESTS_ASSERT(bears == 111);
db.remove_last_cc_hunt();
DB_TESTS_EXCEPTION(db.get_last_cc_hunt(moose, bears));
return true;
}
bool db_tests_cc_trade_used(cryptonote::BlockchainDB &db)
{
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
db.set_cc_trade_used(8, 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
db.set_cc_trade_used(8, 5);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 5);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
db.set_cc_trade_used(8, 6);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 6);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
db.set_cc_trade_used(9, 2);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 6);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 2);
db.set_cc_trade_used(9, 1);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 6);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 1);
db.set_cc_trade_used(8, 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 1);
db.set_cc_trade_used(9, 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(0x1234567890ull) == 0);
db.set_cc_trade_used(0x1234567890ull, 3);
DB_TESTS_ASSERT(db.get_cc_trade_used(0x1234567890ull) == 3);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
db.set_cc_trade_used(9, 2);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 2);
db.set_cc_trade_used(8, 3);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 3);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 2);
db.set_cc_trade_used(8, 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 2);
db.set_cc_trade_used(9, 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(8) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(9) == 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(0x1234567890ull) == 3);
db.set_cc_trade_used(0x1234567890ull, 0);
DB_TESTS_ASSERT(db.get_cc_trade_used(0x1234567890ull) == 0);
return true;
}
bool db_tests_cc_used_nonces(cryptonote::BlockchainDB &db)
{
crypto::hash h = crypto::null_hash, hq;
h.data[0] = 4;
std::vector<uint32_t> a, aq;
a.push_back(2);
a.push_back(3);
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1));
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1, &aq, NULL));
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1, NULL, &hq));
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1, &aq, &hq));
db.add_cc_used_nonce(1, h);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1));
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, NULL, &hq));
DB_TESTS_ASSERT(hq == h);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, &aq, NULL));
DB_TESTS_ASSERT(aq.empty());
unsigned seen = 0;
db.for_all_cc_nonces_used([&seen, &h, &a](uint64_t nonce, const std::vector<uint32_t> &accounts, const crypto::hash &txid){
seen++;
DB_TESTS_ASSERT(accounts.empty());
DB_TESTS_ASSERT(txid == h);
return true;
});
DB_TESTS_ASSERT(seen == 1);
db.remove_cc_used_nonce(1);
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1));
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1, &aq, NULL));
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1, NULL, &hq));
DB_TESTS_ASSERT(!db.is_cc_nonce_used(1, &aq, &hq));
seen = 0;
db.for_all_cc_nonces_used([&seen](uint64_t nonce, const std::vector<uint32_t> &accounts, const crypto::hash &txid){ seen++; return true; });
DB_TESTS_ASSERT(seen == 0);
db.add_cc_used_nonce(1, a);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1));
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, NULL, &hq));
DB_TESTS_ASSERT(hq == crypto::null_hash);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, &aq, NULL));
DB_TESTS_ASSERT(aq == a);
seen = 0;
db.for_all_cc_nonces_used([&seen, &h, &a](uint64_t nonce, const std::vector<uint32_t> &accounts, const crypto::hash &txid){
seen++;
DB_TESTS_ASSERT(accounts == a);
DB_TESTS_ASSERT(txid == crypto::null_hash);
return true;
});
DB_TESTS_ASSERT(seen == 1);
db.add_cc_used_nonce(1, h);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1));
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, NULL, &hq));
DB_TESTS_ASSERT(hq == h);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, &aq, NULL));
DB_TESTS_ASSERT(aq == a);
seen = 0;
db.for_all_cc_nonces_used([&seen, &h, &a](uint64_t nonce, const std::vector<uint32_t> &accounts, const crypto::hash &txid){
seen++;
DB_TESTS_ASSERT(accounts == a);
DB_TESTS_ASSERT(txid == h);
return true;
});
DB_TESTS_ASSERT(seen == 1);
db.add_cc_used_nonce(1, crypto::null_hash);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1));
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, NULL, &hq));
DB_TESTS_ASSERT(hq == crypto::null_hash);
DB_TESTS_ASSERT(db.is_cc_nonce_used(1, &aq, NULL));
DB_TESTS_ASSERT(aq == a);
seen = 0;
db.for_all_cc_nonces_used([&seen, &h, &a](uint64_t nonce, const std::vector<uint32_t> &accounts, const crypto::hash &txid){
seen++;
DB_TESTS_ASSERT(accounts == a);
DB_TESTS_ASSERT(txid == crypto::null_hash);
return true;
});
DB_TESTS_ASSERT(seen == 1);
return true;
}
bool db_tests_cc_whispers(cryptonote::BlockchainDB &db)
{
cc::whisper_t whisper;
whisper.city = 1;
whisper.expiration = 1;
whisper.id = 0x42;
whisper.x = whisper.y = whisper.z = 1;
whisper.rx = whisper.ry = 2;
whisper.red = whisper.green = whisper.blue = 3;
whisper.message = "test 0x42";
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(0, [](const cc::whisper_t&) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_EXCEPTION(db.remove_cc_whisper(whisper));
db.add_cc_whisper(whisper);
int seen = 0;
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(0, [](const cc::whisper_t&) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(1, [&seen, &whisper](const cc::whisper_t &w) { DB_TESTS_ASSERT(w == whisper); ++seen; return true; }));
DB_TESTS_ASSERT(seen == 1);
++whisper.id;
DB_TESTS_EXCEPTION(db.remove_cc_whisper(whisper));
--whisper.id;
db.remove_cc_whisper(whisper);
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(0, [](const cc::whisper_t&) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(1, [](const cc::whisper_t&) { DB_TESTS_ASSERT(false); return true; }));
db.add_cc_whisper(whisper);
++whisper.id;
whisper.city = 0;
db.add_cc_whisper(whisper);
++whisper.id;
++whisper.expiration;
whisper.city = 1;
db.add_cc_whisper(whisper);
// there's now 0x42 (exp 1) and 0x44 (exp 2) in 1, and 0x43 (exp 1) in 0
seen = 0;
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(0, [&seen](const cc::whisper_t &w) { DB_TESTS_ASSERT(w.id == 0x43); ++seen; return true; }));
DB_TESTS_ASSERT(seen == 1);
seen = 0;
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(1, [&seen](const cc::whisper_t &w) { DB_TESTS_ASSERT(w.id == 0x42 || w.id == 0x44); ++seen; return true; }));
DB_TESTS_ASSERT(seen == 2);
whisper.id -= 2;
whisper.city = 1;
--whisper.expiration;
cryptonote::block b;
db.add_block({b, cryptonote::block_to_blob(b)}, 100, 100, 100, 100, 2);
b.prev_id = cryptonote::get_block_hash(b);
b.invalidate_hashes();
db.add_block({b, cryptonote::block_to_blob(b)}, 100, 100, 100, 100, 2);
seen = 0;
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(0, [&seen](const cc::whisper_t &w) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_ASSERT(seen == 0);
seen = 0;
DB_TESTS_ASSERT(db.for_all_active_cc_whispers(1, [&seen](const cc::whisper_t &w) { DB_TESTS_ASSERT(w.id == 0x44); ++seen; return true; }));
DB_TESTS_ASSERT(seen == 1);
return true;
}
bool db_tests_cc_background_scripts(cryptonote::BlockchainDB &db)
{
typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint32_t> ts_t;
std::vector<ts_t> ts;
uint64_t height;
DB_TESTS_EXCEPTION(db.remove_last_cc_background_scripts());
DB_TESTS_EXCEPTION(db.get_last_cc_background_scripts(height, ts));
ts.clear();
ts.push_back(std::make_tuple(1, 2, 3, 4, 5));
db.add_cc_background_scripts(GAME_UPDATE_FREQUENCY, ts);
ts.clear();
db.get_last_cc_background_scripts(height, ts);
DB_TESTS_ASSERT(height == GAME_UPDATE_FREQUENCY);
DB_TESTS_ASSERT(ts.size() == 1);
DB_TESTS_ASSERT(ts[0] == std::make_tuple(1, 2, 3, 4, 5));
ts.clear();
ts.push_back(std::make_tuple(11, 12, 13, 14, 15));
ts.push_back(std::make_tuple(21, 22, 23, 24, 25));
db.add_cc_background_scripts(GAME_UPDATE_FREQUENCY * 2, ts);
ts.clear();
db.get_last_cc_background_scripts(height, ts);
DB_TESTS_ASSERT(height == GAME_UPDATE_FREQUENCY * 2);
DB_TESTS_ASSERT(ts.size() == 2);
DB_TESTS_ASSERT(ts[0] == std::make_tuple(11, 12, 13, 14, 15));
DB_TESTS_ASSERT(ts[1] == std::make_tuple(21, 22, 23, 24, 25));
db.remove_last_cc_background_scripts();
ts.clear();
db.get_last_cc_background_scripts(height, ts);
DB_TESTS_ASSERT(height == GAME_UPDATE_FREQUENCY);
DB_TESTS_ASSERT(ts.size() == 1);
DB_TESTS_ASSERT(ts[0] == std::make_tuple(1, 2, 3, 4, 5));
db.remove_last_cc_background_scripts();
DB_TESTS_EXCEPTION(db.remove_last_cc_background_scripts());
DB_TESTS_EXCEPTION(db.get_last_cc_background_scripts(height, ts));
return true;
}
bool db_tests_cc_places(cryptonote::BlockchainDB &db)
{
cc::place_t place;
place.city = 1;
place.namer = 2;
place.x0 = 20;
place.y0 = 21;
place.x1 = 22;
place.y1 = 23;
place.name = "test 0x42";
place.id = 0;
DB_TESTS_ASSERT(db.for_all_cc_places(0, [](const cc::place_t&) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_EXCEPTION(db.remove_last_cc_place(0));
DB_TESTS_ASSERT(db.add_cc_place(place) == 1);
int seen = 0;
DB_TESTS_ASSERT(db.for_all_cc_places(0, [](const cc::place_t&) { DB_TESTS_ASSERT(false); return true; }));
place.id = 1;
place.height = db.height();
DB_TESTS_ASSERT(db.for_all_cc_places(1, [&seen, &place](const cc::place_t &p) { DB_TESTS_ASSERT(p == place); ++seen; return true; }));
DB_TESTS_ASSERT(seen == 1);
DB_TESTS_EXCEPTION(db.remove_last_cc_place(0));
DB_TESTS_EXCEPTION(db.remove_last_cc_place(2));
DB_TESTS_EXCEPTION(db.remove_last_cc_place(0x42));
db.remove_last_cc_place(1);
DB_TESTS_ASSERT(db.for_all_cc_places(0, [](const cc::place_t&) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_ASSERT(db.for_all_cc_places(1, [](const cc::place_t&) { DB_TESTS_ASSERT(false); return true; }));
DB_TESTS_ASSERT(db.add_cc_place(place) == 1);
++place.x0;
++place.y0;
++place.x1;
++place.y1;
place.name = "test 0x43";
DB_TESTS_ASSERT(db.add_cc_place(place) == 2);
// there's now 0x42 and 0x43, partially overlapping
DB_TESTS_ASSERT(db.for_all_cc_places(0, [](const cc::place_t&) { DB_TESTS_ASSERT(false); return true; }));
seen = 0;
DB_TESTS_ASSERT(db.for_all_cc_places(1, [&seen](const cc::place_t &p) {
const bool is_first = p.name == "test 0x42" && p.id == 1;
const bool is_second = p.name == "test 0x43" && p.id == 2;
DB_TESTS_ASSERT(is_first || is_second);
++seen;
return true;
}));
DB_TESTS_ASSERT(seen == 2);
return true;
}
bool db_tests_cc_user_textures(cryptonote::BlockchainDB &db)
{
uint8_t block;
uint32_t creator, width, height, hscale, vscale;
std::string description;
uint64_t creation_height;
bool recent;
cryptonote::block b;
db.add_block({b, cryptonote::block_to_blob(b)}, 100, 100, 100, 100, 2);
db.for_all_cc_textures([](uint32_t, uint64_t, uint8_t, uint32_t, uint32_t, uint32_t, const std::string&, uint32_t, uint32_t, uint64_t, bool){ DB_TESTS_ASSERT(false); return true; });
DB_TESTS_EXCEPTION(db.get_cc_texture_blob(1, block, creator, width, height, description, hscale, vscale, creation_height, recent));
DB_TESTS_EXCEPTION(db.delete_cc_texture(1));
uint32_t texture = db.allocate_new_cc_texture(0x42, 2, 1, 512, 512, "user texture", 6, 12);
DB_TESTS_ASSERT(texture == 1);
for (int i = 0; i < 2; ++i)
{
int seen = 0;
db.for_all_cc_textures([&seen](uint32_t texture, uint64_t nonce, uint8_t block, uint32_t creator, uint32_t width, uint32_t height, const std::string &description, uint32_t hscale, uint32_t vscale, uint64_t creation_height, bool recent){
DB_TESTS_ASSERT(texture == 1);
DB_TESTS_ASSERT(nonce == 0x42);
DB_TESTS_ASSERT(block == 2);
DB_TESTS_ASSERT(creator == 1);
DB_TESTS_ASSERT(width == 512);
DB_TESTS_ASSERT(height == 512);
DB_TESTS_ASSERT(description == "user texture");
DB_TESTS_ASSERT(hscale == 6);
DB_TESTS_ASSERT(vscale == 12);
DB_TESTS_ASSERT(creation_height == 1);
DB_TESTS_ASSERT(recent);
++seen;
return true;
}, i == 1);
DB_TESTS_ASSERT(seen == (i == 1 ? 1 : 0));
}
DB_TESTS_ASSERT(!db.does_cc_texture_exist(1, false));
DB_TESTS_ASSERT(db.does_cc_texture_exist(1, true));
DB_TESTS_ASSERT(!db.does_cc_texture_exist(0));
DB_TESTS_ASSERT(!db.does_cc_texture_exist(2));
DB_TESTS_EXCEPTION(db.delete_cc_texture(2));
db.delete_cc_texture(1);
DB_TESTS_ASSERT(!db.does_cc_texture_exist(1));
db.for_all_cc_textures([](uint32_t, uint64_t, uint8_t, uint32_t, uint32_t, uint32_t, const std::string&, uint32_t, uint32_t, uint64_t, bool){ DB_TESTS_ASSERT(false); return true; });
DB_TESTS_EXCEPTION(db.get_cc_texture_blob(1, block, creator, width, height, description, hscale, vscale, creation_height, recent));
DB_TESTS_EXCEPTION(db.delete_cc_texture(1));
return true;
}
bool db_tests_cc_merchant_ship_available_items(cryptonote::BlockchainDB &db)
{
std::vector<cc::merchant_ship_available_item_t> items;
db.get_cc_merchant_ship_available_items(items);
DB_TESTS_ASSERT(items.empty());
items.push_back({4, 10, 11, 12});
items.push_back({3, 20, 21, 22});
db.set_cc_merchant_ship_available_items(items);
items.clear();
db.get_cc_merchant_ship_available_items(items);
DB_TESTS_ASSERT(items.size() == 2);
// they get sorted by item
DB_TESTS_ASSERT(items[0] == cc::merchant_ship_available_item_t({3, 20, 21, 22}));
DB_TESTS_ASSERT(items[1] == cc::merchant_ship_available_item_t({4, 10, 11, 12}));
items.clear();
items.push_back({1, 2, 3, 4});
db.set_cc_merchant_ship_available_items(items);
items.clear();
db.get_cc_merchant_ship_available_items(items);
DB_TESTS_ASSERT(items.size() == 1);
DB_TESTS_ASSERT(items[0] == cc::merchant_ship_available_item_t({1, 2, 3, 4}));
items.clear();
db.set_cc_merchant_ship_available_items(items);
db.get_cc_merchant_ship_available_items(items);
DB_TESTS_ASSERT(items.empty());
return true;
}
bool db_tests_cc_merchant_ships(cryptonote::BlockchainDB &db)
{
uint32_t city, chan;
uint64_t height;
std::string ship_name, origin;
std::vector<uint64_t> nonces;
std::vector<std::tuple<uint32_t, uint32_t, uint64_t, std::vector<uint64_t>>> new_items;
std::vector<std::tuple<uint32_t, uint32_t, uint64_t, uint32_t, std::vector<uint64_t>>> items;
const uint32_t channel = cc::SPECIAL_EVENT_CHANNEL_TRADE1;
DB_TESTS_ASSERT(!db.get_cc_merchant_ship_data(0, channel, height, ship_name, origin, items));
DB_TESTS_EXCEPTION(db.remove_cc_merchant_ship(0, channel));
DB_TESTS_EXCEPTION(db.increase_cc_merchant_ship_sold(0, channel, 1, 1));
DB_TESTS_EXCEPTION(db.decrease_cc_merchant_ship_sold(0, channel, 1, 1));
DB_TESTS_ASSERT(!db.is_cc_merchant_ship_transaction(0, city, chan));
for (uint64_t i = 0; i < 3; ++i)
nonces.push_back(1 + i);
new_items.push_back(std::make_tuple(ITEM_FIRST_USER + 42, 3000, 60000, nonces));
db.add_cc_merchant_ship(0, channel, 6, "Seagull", "Far away", new_items);
new_items.clear();
new_items.push_back(std::make_tuple(ITEM_FIRST_USER + 43, 1000, 90000, nonces));
DB_TESTS_EXCEPTION(db.add_cc_merchant_ship(0, channel, 1, "Kingfisher", "Further away", new_items));
DB_TESTS_ASSERT(!db.get_cc_merchant_ship_data(1, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(0, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(height == 6);
DB_TESTS_ASSERT(ship_name == "Seagull");
DB_TESTS_ASSERT(origin == "Far away");
DB_TESTS_ASSERT(items.size() == 1);
DB_TESTS_ASSERT(std::get<0>(items[0]) == ITEM_FIRST_USER + 42);
DB_TESTS_ASSERT(std::get<1>(items[0]) == 3000);
DB_TESTS_ASSERT(std::get<2>(items[0]) == 60000);
DB_TESTS_ASSERT(std::get<3>(items[0]) == 0);
DB_TESTS_ASSERT(std::get<4>(items[0]).size() == 3);
DB_TESTS_ASSERT(std::get<4>(items[0])[0] == 1);
DB_TESTS_ASSERT(std::get<4>(items[0])[1] == 2);
DB_TESTS_ASSERT(std::get<4>(items[0])[2] == 3);
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(1, city, chan) && city == 0 && chan == channel);
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(2, city, chan) && city == 0 && chan == channel);
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(3, city, chan) && city == 0 && chan == channel);
DB_TESTS_ASSERT(!db.is_cc_merchant_ship_transaction(4, city, chan));
DB_TESTS_EXCEPTION(db.decrease_cc_merchant_ship_sold(0, channel, 1, 1));
DB_TESTS_EXCEPTION(db.increase_cc_merchant_ship_sold(0, channel, ITEM_FIRST_USER + 41, 500));
db.increase_cc_merchant_ship_sold(0, channel, ITEM_FIRST_USER + 42, 500);
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(0, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(items.size() == 1);
DB_TESTS_ASSERT(std::get<3>(items[0]) == 500);
nonces.clear();
for (int i = 3; i < 5; ++i)
nonces.push_back(1 + i);
new_items.clear();
new_items.push_back(std::make_tuple(ITEM_FIRST_USER + 43, 1000, 90000, nonces));
db.add_cc_merchant_ship(1, channel, 30, "Kingfisher", "Further away", new_items);
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(1, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(height == 30);
DB_TESTS_ASSERT(ship_name == "Kingfisher");
DB_TESTS_ASSERT(origin == "Further away");
DB_TESTS_ASSERT(items.size() == 1);
DB_TESTS_ASSERT(std::get<0>(items[0]) == ITEM_FIRST_USER + 43);
DB_TESTS_ASSERT(std::get<1>(items[0]) == 1000);
DB_TESTS_ASSERT(std::get<2>(items[0]) == 90000);
DB_TESTS_ASSERT(std::get<3>(items[0]) == 0);
DB_TESTS_ASSERT(std::get<4>(items[0]).size() == 2);
DB_TESTS_ASSERT(std::get<4>(items[0])[0] == 4);
DB_TESTS_ASSERT(std::get<4>(items[0])[1] == 5);
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(4, city, chan) && city == 1 && chan == channel);
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(5, city, chan) && city == 1 && chan == channel);
db.increase_cc_merchant_ship_sold(1, channel, ITEM_FIRST_USER + 43, 200);
db.increase_cc_merchant_ship_sold(0, channel, ITEM_FIRST_USER + 42, 500);
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(0, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(std::get<3>(items[0]) == 1000);
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(1, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(std::get<3>(items[0]) == 200);
DB_TESTS_EXCEPTION(db.decrease_cc_merchant_ship_sold(1, channel, ITEM_FIRST_USER + 43, 201));
DB_TESTS_EXCEPTION(db.decrease_cc_merchant_ship_sold(0, channel, ITEM_FIRST_USER + 43, 1001));
db.decrease_cc_merchant_ship_sold(1, channel, ITEM_FIRST_USER + 43, 200);
db.decrease_cc_merchant_ship_sold(0, channel, ITEM_FIRST_USER + 42, 1000);
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(0, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(std::get<3>(items[0]) == 0);
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(1, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(std::get<3>(items[0]) == 0);
db.remove_cc_merchant_ship(0, channel);
DB_TESTS_ASSERT(!db.get_cc_merchant_ship_data(0, channel, height, ship_name, origin, items));
DB_TESTS_ASSERT(db.get_cc_merchant_ship_data(1, channel, height, ship_name, origin, items));
DB_TESTS_EXCEPTION(db.remove_cc_merchant_ship(0, channel));
DB_TESTS_ASSERT(!db.is_cc_merchant_ship_transaction(1, city, chan));
DB_TESTS_ASSERT(!db.is_cc_merchant_ship_transaction(2, city, chan));
DB_TESTS_ASSERT(!db.is_cc_merchant_ship_transaction(3, city, chan));
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(4, city, chan) && city == 1 && chan == channel);
DB_TESTS_ASSERT(db.is_cc_merchant_ship_transaction(5, city, chan) && city == 1 && chan == channel);
db.remove_cc_merchant_ship(1, channel);
return true;
}
bool db_tests_cc_epochs(cryptonote::BlockchainDB &db)
{
std::vector<cc::cc_epoch_t> epochs;
epochs = db.get_cc_epochs();
DB_TESTS_ASSERT(epochs.empty());
DB_TESTS_EXCEPTION(db.remove_cc_last_epoch());
DB_TESTS_EXCEPTION(db.get_cc_epoch(0));
const cc::cc_epoch_t e0Landfall_open_ended{0, "Landfall", 0, (int64_t)-1};
const cc::cc_epoch_t e0Landfall_over{0, "Landfall", 0, 2};
const cc::cc_epoch_t e1Exploration{1, "Exploration", 2, (int64_t)-1};
db.start_cc_epoch("Landfall"); // at 0
DB_TESTS_ASSERT(db.get_cc_epoch(0) == e0Landfall_open_ended);
DB_TESTS_ASSERT(db.get_cc_epoch(1) == e0Landfall_open_ended);
epochs = db.get_cc_epochs();
DB_TESTS_ASSERT(epochs.size() == 1);
DB_TESTS_ASSERT(epochs[0] == e0Landfall_open_ended);
cryptonote::block b;
db.add_block({b, cryptonote::block_to_blob(b)}, 100, 100, 100, 100, 2);
b.prev_id = cryptonote::get_block_hash(b);
b.invalidate_hashes();
db.add_block({b, cryptonote::block_to_blob(b)}, 100, 100, 100, 100, 2);
db.start_cc_epoch("Exploration"); // at 2
DB_TESTS_ASSERT(db.get_cc_epoch(0) == e0Landfall_over);
DB_TESTS_ASSERT(db.get_cc_epoch(1) == e0Landfall_over);
DB_TESTS_ASSERT(db.get_cc_epoch(2) == e1Exploration);
epochs = db.get_cc_epochs();
DB_TESTS_ASSERT(epochs.size() == 2);
DB_TESTS_ASSERT(epochs[0] == e0Landfall_over);
DB_TESTS_ASSERT(epochs[1] == e1Exploration);
db.remove_cc_last_epoch();
epochs = db.get_cc_epochs();
DB_TESTS_ASSERT(epochs.size() == 1);
DB_TESTS_ASSERT(epochs[0] == e0Landfall_open_ended);
DB_TESTS_ASSERT(db.get_cc_epoch(0) == e0Landfall_open_ended);
DB_TESTS_ASSERT(db.get_cc_epoch(1) == e0Landfall_open_ended);
db.remove_cc_last_epoch();
epochs = db.get_cc_epochs();
DB_TESTS_ASSERT(epochs.empty());
DB_TESTS_EXCEPTION(db.get_cc_epoch(0));
DB_TESTS_EXCEPTION(db.remove_cc_last_epoch());
return true;
}
bool db_tests_cc_coru_requests(cryptonote::BlockchainDB &db)
{
std::vector<cc::coru_request_t> requests;
cc::coru_request_t request;
crypto::hash hash1, hash2;
hash1 = crypto::null_hash;
hash1.data[4] = 1;
hash2 = crypto::null_hash;
hash2.data[4] = 2;
db.get_cc_coru_requests(requests);
DB_TESTS_ASSERT(requests.empty());
request.nonce = 0x80;
request.account = 5;
request.player = 7;
request.until_height = 77;
request.min_wager = 35;
request.max_wager = 53;
request.deck_commitment = hash2;
db.add_cc_coru_request(hash1, request);
db.get_cc_coru_requests(requests);
DB_TESTS_ASSERT(requests.size() == 1);
DB_TESTS_ASSERT(requests[0].nonce == 0x80);
DB_TESTS_ASSERT(requests[0].account == 5);
DB_TESTS_ASSERT(requests[0].player == 7);
DB_TESTS_ASSERT(requests[0].until_height == 77);
DB_TESTS_ASSERT(requests[0].min_wager == 35);
DB_TESTS_ASSERT(requests[0].max_wager == 53);
DB_TESTS_ASSERT(requests[0].deck_commitment == hash2);
db.remove_cc_coru_request(0x100); // nop
db.get_cc_coru_requests(requests);
DB_TESTS_ASSERT(requests.size() == 1);
db.remove_cc_coru_request(0x80);
db.get_cc_coru_requests(requests);
DB_TESTS_ASSERT(requests.empty());
return true;
}
bool db_tests_cc_coru_games(cryptonote::BlockchainDB &db)
{
cc::coru_game_state_t coru;
uint32_t found = 0;
db.for_all_cc_coru_games([&found](const cc::coru_game_state_t &c) { ++found; return true; }, false);
DB_TESTS_ASSERT(found == 0);
db.for_all_cc_coru_games([&found](const cc::coru_game_state_t &c) { ++found; return true; }, true);
DB_TESTS_ASSERT(found == 0);
DB_TESTS_EXCEPTION(db.get_last_cc_coru_game_id());
DB_TESTS_EXCEPTION(db.delete_last_cc_coru_game());
DB_TESTS_ASSERT(!db.get_cc_coru_game(0, coru));
DB_TESTS_ASSERT(!db.get_cc_coru_game(1, coru));
cc::coru_player_t players[2];
players[0].id = 35;
players[0].commitment = crypto::null_hash;
players[0].commitment.data[21] = 0x42;
players[0].deck.coins.push_back(4);
players[0].deck.coins.push_back(6);
players[0].deck.runes.push_back(4098);
players[1].id = 111111;
players[1].commitment = crypto::null_hash;
players[1].commitment.data[5] = 0x21;
players[0].deck.coins.push_back(400);
players[0].deck.coins.push_back(500);
players[0].deck.runes.clear();
uint32_t id1 = db.start_cc_coru_game(players, "foo", 12, false, 4, 30);
DB_TESTS_ASSERT(id1 == 1);
DB_TESTS_ASSERT(db.get_last_cc_coru_game_id() == 1);
const uint64_t height = db.height();
cc::coru_game_state_t cr;
for (int i = 0; i < 2; ++i)
{
found = 0;
db.for_all_cc_coru_games([&players, height, &found, &cr](const cc::coru_game_state_t &c) {
DB_TESTS_ASSERT(c.id == 1);
DB_TESTS_ASSERT(c.name == "foo");
DB_TESTS_ASSERT(c.winner == 0);
DB_TESTS_ASSERT(c.players[0] == players[0]);
DB_TESTS_ASSERT(c.players[1] == players[1]);
DB_TESTS_ASSERT(c.rounds.size() == 1);
DB_TESTS_ASSERT(c.rounds[0].turn == 0);
DB_TESTS_ASSERT(c.rounds[0].start_height == height);
DB_TESTS_ASSERT(c.rounds[0].first_player_index == 0);
DB_TESTS_ASSERT(c.rounds[0].outcome == CORU_ROUND_ONGOING);
DB_TESTS_ASSERT(c.game_start_height == height);
DB_TESTS_ASSERT(c.game_turn == 0);
DB_TESTS_ASSERT(c.turn_start_height == height);
DB_TESTS_ASSERT(c.rounds_to_win == 4);
DB_TESTS_ASSERT(c.wager == 12);
DB_TESTS_ASSERT(!c.jeopardy);
DB_TESTS_ASSERT(c.max_turn_time == 30);
++found;
cr = c;
return true;
}, i == 0);
DB_TESTS_ASSERT(found == 1);
}
DB_TESTS_ASSERT(!db.get_cc_coru_game(0, coru));
DB_TESTS_ASSERT(db.get_cc_coru_game(1, coru));
DB_TESTS_ASSERT(coru == cr);
DB_TESTS_ASSERT(!db.get_cc_coru_game(2, coru));
db.delete_last_cc_coru_game();
DB_TESTS_EXCEPTION(db.delete_last_cc_coru_game());
found = 0;
db.for_all_cc_coru_games([&found](const cc::coru_game_state_t &c) { ++found; return true; }, false);
DB_TESTS_ASSERT(found == 0);
db.for_all_cc_coru_games([&found](const cc::coru_game_state_t &c) { ++found; return true; }, true);
DB_TESTS_ASSERT(found == 0);
DB_TESTS_ASSERT(!db.get_cc_coru_game(0, coru));
DB_TESTS_ASSERT(!db.get_cc_coru_game(1, coru));
DB_TESTS_EXCEPTION(db.get_last_cc_coru_game_id());
return true;
}
bool db_tests_cc_coru_tournaments(cryptonote::BlockchainDB &db)
{
cc::coru_tournament_state_t coru;
uint32_t found = 0;
db.for_all_cc_coru_tournaments([&found](const cc::coru_tournament_state_t &c) { ++found; return true; }, false);
DB_TESTS_ASSERT(found == 0);
db.for_all_cc_coru_tournaments([&found](const cc::coru_tournament_state_t &c) { ++found; return true; }, true);
DB_TESTS_ASSERT(found == 0);
DB_TESTS_EXCEPTION(db.get_last_cc_coru_tournament_id());
DB_TESTS_EXCEPTION(db.delete_last_cc_coru_tournament());
DB_TESTS_ASSERT(!db.get_cc_coru_tournament(0, coru));
DB_TESTS_ASSERT(!db.get_cc_coru_tournament(1, coru));
std::vector<std::pair<uint64_t, std::vector<std::pair<uint32_t, uint32_t>>>> prizes(2);
prizes[0].first = 255;
prizes[0].second.push_back(std::make_pair(7, 8));
prizes[1].first = 2555;
prizes[1].second.push_back(std::make_pair(2, 4));
prizes[1].second.push_back(std::make_pair(6, 8));
uint32_t id1 = db.create_cc_coru_tournament("bar", 60, prizes, 888, 130);
DB_TESTS_ASSERT(id1 == 1);
DB_TESTS_ASSERT(db.get_last_cc_coru_tournament_id() == 1);
const uint64_t height = db.height();
cc::coru_tournament_state_t cr;
for (int i = 0; i < 2; ++i)
{
found = 0;
db.for_all_cc_coru_tournaments([&prizes, height, &found, &cr](const cc::coru_tournament_state_t &c) {
DB_TESTS_ASSERT(c.id == 1);
DB_TESTS_ASSERT(c.creator == 60);
DB_TESTS_ASSERT(c.name == "bar");
DB_TESTS_ASSERT(c.end_height == 0);
DB_TESTS_ASSERT(c.entrants.empty());
DB_TESTS_ASSERT(c.prizes == prizes);
DB_TESTS_ASSERT(c.start_height == 888);
DB_TESTS_ASSERT(c.registration_fee == 130);
DB_TESTS_ASSERT(c.n_rounds == 0);
DB_TESTS_ASSERT(c.rounds.empty());
DB_TESTS_ASSERT(c.byes.empty());
DB_TESTS_ASSERT(c.wins.empty());
++found;
cr = c;
return true;
}, i == 0);
DB_TESTS_ASSERT(found == 1);
}
DB_TESTS_ASSERT(!db.get_cc_coru_tournament(0, coru));
DB_TESTS_ASSERT(db.get_cc_coru_tournament(1, coru));
DB_TESTS_ASSERT(coru == cr);
DB_TESTS_ASSERT(!db.get_cc_coru_tournament(2, coru));
db.delete_last_cc_coru_tournament();
DB_TESTS_EXCEPTION(db.delete_last_cc_coru_tournament());
found = 0;
db.for_all_cc_coru_tournaments([&found](const cc::coru_tournament_state_t &c) { ++found; return true; }, false);
DB_TESTS_ASSERT(found == 0);
db.for_all_cc_coru_tournaments([&found](const cc::coru_tournament_state_t &c) { ++found; return true; }, true);
DB_TESTS_ASSERT(found == 0);
DB_TESTS_ASSERT(!db.get_cc_coru_tournament(0, coru));
DB_TESTS_ASSERT(!db.get_cc_coru_tournament(1, coru));
DB_TESTS_EXCEPTION(db.get_last_cc_coru_tournament_id());
return true;
}
bool db_tests_cc_trustee_balances(cryptonote::BlockchainDB &db)
{
std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> balances;
crypto::public_key key1 = crypto::null_pkey; key1.data[0] = 1;
crypto::public_key key2 = crypto::null_pkey; key2.data[0] = 2;
crypto::public_key key3 = crypto::null_pkey; key3.data[0] = 3;
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.empty());
db.change_cc_trustee_balance(key1, 0, 0);
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.empty());
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key2) == std::make_pair(0ul, 0ul));
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, -1, 0));
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, 0, -1));
db.change_cc_trustee_balance(key1, 0, 18);
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, 0, -19));
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(0ul, 18ul));
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.size() == 1);
DB_TESTS_ASSERT(balances.begin()->first == key1);
DB_TESTS_ASSERT(balances.begin()->second.first == 0);
DB_TESTS_ASSERT(balances.begin()->second.second == 18);
db.change_cc_trustee_balance(key2, 2, 0);
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.size() == 2);
DB_TESTS_ASSERT(balances.find(key1) != balances.end());
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
DB_TESTS_ASSERT(balances.find(key1)->second.first == 0);
DB_TESTS_ASSERT(balances.find(key1)->second.second == 18);
DB_TESTS_ASSERT(balances.find(key2)->second.first == 2);
DB_TESTS_ASSERT(balances.find(key2)->second.second == 0);
db.change_cc_trustee_balance(key2, 40, 6);
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.size() == 2);
DB_TESTS_ASSERT(balances.find(key1) != balances.end());
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
DB_TESTS_ASSERT(balances.find(key1)->second == std::make_pair(0ul, 18ul));
DB_TESTS_ASSERT(balances.find(key2)->second == std::make_pair(42ul, 6ul));
db.change_cc_trustee_balance(key1, 0, -18);
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.size() == 1);
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
DB_TESTS_ASSERT(balances.find(key2)->second == std::make_pair(42ul, 6ul));
db.change_cc_trustee_balance(key1, 8, 5);
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.size() == 2);
DB_TESTS_ASSERT(balances.find(key1) != balances.end());
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
DB_TESTS_ASSERT(balances.find(key1)->second == std::make_pair(8ul, 5ul));
DB_TESTS_ASSERT(balances.find(key2)->second == std::make_pair(42ul, 6ul));
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(8ul, 5ul));
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key2) == std::make_pair(42ul, 6ul));
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key3) == std::make_pair(0ul, 0ul));
db.change_cc_trustee_balance(key1, 2, -2);
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(10ul, 3ul));
db.change_cc_trustee_balance(key1, -5, -2);
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(5ul, 1ul));
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, -6, 10));
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, 10, -2));
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, -6, -2));
db.change_cc_trustee_balance(key1, -5, -1);
db.change_cc_trustee_balance(key2, -42, -6);
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(0ul, 0ul));
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key2) == std::make_pair(0ul, 0ul));
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key3) == std::make_pair(0ul, 0ul));
db.get_cc_trustee_balances(balances);
DB_TESTS_ASSERT(balances.empty());
return true;
}
bool db_tests_cc_flag_ownership_changes(cryptonote::BlockchainDB &db)
{
DB_TESTS_ASSERT(cc::add_init_state(db));
DB_TESTS_EXCEPTION(db.revert_cc_flag_ownership_changes(0, 1));
DB_TESTS_EXCEPTION(db.revert_cc_flag_ownership_changes(1, 1));
DB_TESTS_EXCEPTION(db.revert_cc_flag_ownership_changes(2, 1));
cryptonote::cc_flag_data_t fd;
DB_TESTS_ASSERT(db.get_cc_flag_data(1, fd));
fd.recent_ownership_changes = 0;
db.set_cc_flag_data(1, fd);
DB_TESTS_EXCEPTION(db.record_cc_flag_ownership_changes(1, 1));
fd.recent_ownership_changes = 7498;
db.set_cc_flag_data(1, fd);
db.record_cc_flag_ownership_changes(1, 1);
DB_TESTS_EXCEPTION(db.record_cc_flag_ownership_changes(1, 1));
DB_TESTS_ASSERT(db.get_cc_flag_data(1, fd));
DB_TESTS_ASSERT(fd.recent_ownership_changes == 0);
DB_TESTS_EXCEPTION(db.record_cc_flag_ownership_changes(1, 1));
DB_TESTS_EXCEPTION(db.revert_cc_flag_ownership_changes(1, 2));
DB_TESTS_EXCEPTION(db.revert_cc_flag_ownership_changes(2, 1));
db.revert_cc_flag_ownership_changes(1, 1);
DB_TESTS_EXCEPTION(db.revert_cc_flag_ownership_changes(1, 1));
DB_TESTS_ASSERT(db.get_cc_flag_data(1, fd));
DB_TESTS_ASSERT(fd.recent_ownership_changes == 7498);
return true;
}