townforge/tests/db_tests/db_tests_cc.cpp
2021-04-15 11:12:21 +00:00

483 lines
17 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 "blockchain_db/blockchain_db.h"
#include "cc/cc_script.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", 42, true);
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);
++n_scripts;
return true;
}));
DB_TESTS_ASSERT(n_scripts == 1);
const uint32_t id2 = db.allocate_new_cc_script("name2", "icon2", "desc2", "blob2", 43, false);
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);
++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_cc_script_effects(4, 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.set_cc_script_effects(4, test_effects);
db.get_cc_script_effects(4, 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.set_cc_script_effects(5, test_effects);
db.delete_cc_script_effects(4);
DB_TESTS_EXCEPTION(db.get_cc_script_effects(4, effects));
db.get_cc_script_effects(5, 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_cc_script_effects(5);
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, "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.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, 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, 200, 200));
db.add_cc_auction_bid(1, 3, 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, 200, 200));
DB_TESTS_ASSERT(ad.bids[1] == std::make_tuple(3, 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_cc_auction_bid(1, 3, 400, 300);
db.remove_cc_auction_bid(1, 2, 200, 200);
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;
}