townforge/tests/core_tests/cc.cpp
Crypto City 1c9075daf5 avatars can now select model and pronouns
though there is still only one model for now

also various tweaks and improvements to the avatar selection ui
2025-08-08 17:35:15 +00:00

4114 lines
173 KiB
C++

// Copyright (c) 2014-2019, The Monero Project
//
// 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <boost/algorithm/string.hpp>
#include "ringct/rctSigs.h"
#include "chaingen.h"
#include "ringct/rctTypes.h"
#include "cryptonote_basic/stake.h"
#include "cc.h"
#include "cc/cc_game_update.h"
#include "device/device.hpp"
using namespace epee;
using namespace crypto;
using namespace cryptonote;
#define BASE_TEST_FORK 16
#define DEFAULT_MIXIN 15
#define INITIAL_AUTO_FUNDING (17*COIN - CRYPTONOTE_CC_NEW_ACCOUNT_FEE)
#define BARE_TX_FEE 3000000
#define STARTING_BLOCK_1 400
#define STARTING_BLOCK_2 1500
#define STARTING_LABOUR 8500
#define N_LARGE_BALANCE_OUTS 350
#define PREDEFINED_BUILDINGS 1
#define FIRST_TEST_ACCOUNT 5
#define CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD (CRYPTONOTE_CC_NEW_ACCOUNT_FEE - NEWBIE_COIN_GOLD_CONTENT)
#define PREP_BUY_LAND_X 140
#define PREP_BUY_LAND_Y 20
#define PREP_BUY_LAND_WM1 11
#define PREP_BUY_LAND_HM1 11
#define DEFAULT_AVATAR_SETTINGS 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0
static cryptonote::account_base cc_test_accounts[8];
static const uint64_t initial_funding[8] = {
INITIAL_AUTO_FUNDING,
INITIAL_AUTO_FUNDING,
INITIAL_AUTO_FUNDING,
CRYPTONOTE_CC_NEW_ACCOUNT_FEE + 1,
INITIAL_AUTO_FUNDING,
INITIAL_AUTO_FUNDING,
INITIAL_AUTO_FUNDING,
INITIAL_AUTO_FUNDING
};
static uint64_t expected_balance[8] = {
0, 0, 0, 0, 0, 0, 0, 0
};
static uint64_t expected_treasury_balance = 0;
static cryptonote::account_base dummy_change_account;
static void init_cc_test_accounts()
{
static bool init = false;
if (init)
return;
init = true;
for (size_t i = 0; i < sizeof(cc_test_accounts) / sizeof(cc_test_accounts[0]); ++i)
{
cc_test_accounts[i].generate();
}
dummy_change_account.generate();
}
static bool log_test_accounts(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
BlockchainDB &db = c.get_blockchain_storage().get_db();
uint64_t total_money_in_accounts = 0, total_money_in_blockchain = 0;
static const char *name[5] = { "invalid", "mayor", "game", "foreclosure", "treasury" };
for (uint32_t n = 0; n < sizeof(name) / sizeof(name[0]); ++n)
{
crypto::public_key public_key;
uint64_t balance;
if (db.get_cc_account_transactional_data(n, public_key, balance))
{
MDEBUG(" account " << n << " (" << name[n] << "): " << public_key << ", balance " << cryptonote::print_money(balance));
total_money_in_accounts += balance;
}
}
std::vector<block> block_list;
bool r = c.get_blocks(0, c.get_current_blockchain_height(), block_list);
if (!r)
{
MERROR("Failed to get blocks");
return false;
}
std::vector<block> blocks(block_list.begin(), block_list.end());
std::vector<cryptonote::block> chain;
map_hash2tx_t mtx;
const crypto::hash block_hash = get_block_hash(block_list.back());
r = find_block_chain(events, chain, mtx, block_hash);
if (!r)
{
MERROR("Failed to find blockchain");
return false;
}
for (uint32_t n = 0; n < sizeof(cc_test_accounts) / sizeof(cc_test_accounts[0]); ++n)
{
uint64_t account_balance, blockchain_balance;
const crypto::public_key spend_public_key = cc::get_cc_public_key(cc_test_accounts[n].get_keys().m_spend_secret_key);
uint32_t id;
if (!db.lookup_cc_account(spend_public_key, id) || !db.get_cc_account_balance(id, account_balance))
account_balance = 0;
std::map<uint32_t, uint32_t> item_balances;
if (db.get_cc_account_item_balances(id, item_balances))
{
for (const auto &e: item_balances)
{
if (e.first < ITEM_FIRST_USER || e.first > ITEM_LAST_USER)
continue;
cc::cc_custom_item_t cid;
if (!db.get_cc_custom_item_data(e.first, cid))
{
MERROR("Failed to get item data");
return false;
}
if (cid.is_group)
continue;
account_balance += e.second * cid.gold;
}
}
blockchain_balance = get_balance(cc_test_accounts[n], blocks, mtx);
MDEBUG(" account " << n << ": " << spend_public_key
<< ", game account balance " << cryptonote::print_money(account_balance)
<< ", blockchain balance " << cryptonote::print_money(blockchain_balance));
total_money_in_accounts += account_balance;
total_money_in_blockchain += blockchain_balance;
}
MDEBUG("Total money in game accounts: " << cryptonote::print_money(total_money_in_accounts));
MDEBUG("Total money in blockchain: " << cryptonote::print_money(total_money_in_blockchain));
MDEBUG("Total money in both: " << cryptonote::print_money(total_money_in_accounts + total_money_in_blockchain));
const auto coinbase_tx_sum = c.get_coinbase_tx_sum(0, c.get_current_blockchain_height());
const boost::multiprecision::uint128_t emission = std::get<0>(coinbase_tx_sum);
const boost::multiprecision::uint128_t subsidy = std::get<2>(coinbase_tx_sum);
MDEBUG("Total coinbase emission: " << cryptonote::print_money(emission));
MDEBUG("Total game subsidy: " << cryptonote::print_money(subsidy));
if (emission > std::numeric_limits<uint64_t>::max() || subsidy > std::numeric_limits<uint64_t>::max())
{
MERROR("emission or subsidy too high");
return false;
}
if (total_money_in_accounts + total_money_in_blockchain != emission + subsidy)
{
MERROR("Some money is unaccounted for");
if (total_money_in_accounts + total_money_in_blockchain < emission + subsidy)
MERROR("Some money was destroyed: " << cryptonote::print_money(emission + subsidy - (total_money_in_accounts + total_money_in_blockchain)));
else
MERROR("More money exists than mined: " << cryptonote::print_money(total_money_in_accounts + total_money_in_blockchain - emission - subsidy));
return false;
}
return true;
}
static bool expect_cc_account(cryptonote::core &c, int idx, uint32_t expected_id, uint64_t expected_balance)
{
BlockchainDB &db = c.get_blockchain_storage().get_db();
uint32_t id;
const crypto::public_key pkey = cc::get_cc_public_key(cc_test_accounts[idx].get_keys().m_spend_secret_key);
if (!db.lookup_cc_account(pkey, id))
{
MERROR("Account " << idx << " (" << pkey << ") not found in database");
return false;
}
if (id != expected_id)
{
MERROR("Account has unexpected id");
return false;
}
crypto::public_key public_key;
uint64_t balance;
if (!db.get_cc_account_transactional_data(id, public_key, balance))
{
MERROR("Account transactional data not found in database");
return false;
}
if (public_key != pkey)
{
MERROR("Account has unexpected spend public key");
return false;
}
if (balance != expected_balance)
{
MERROR("Account " << idx << " has unexpected balance: expected " << cryptonote::print_money(expected_balance) << ", got " << cryptonote::print_money(balance));
return false;
}
return true;
}
static bool expect_treasury_balance(cryptonote::core &c, uint64_t expected_balance)
{
BlockchainDB &db = c.get_blockchain_storage().get_db();
uint32_t treasury;
if (!db.get_cc_city_treasury(0, treasury))
{
MERROR("City 0 treasury not found");
return false;
}
uint64_t balance;
if (!db.get_cc_account_balance(treasury, balance))
{
MERROR("City 0 treasury account not found");
return false;
}
if (balance != expected_balance)
{
MERROR("City 0 treasury account has unexpected balance: " << cryptonote::print_money(balance) << ", expected " << cryptonote::print_money(expected_balance));
return false;
}
return true;
}
static uint64_t get_subsidy_total(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
uint64_t subsidy = 0;
for (size_t i = 0; i < events.size(); ++i)
{
const auto &e = events[i];
if (e.type() != typeid(cryptonote::block))
continue;
const cryptonote::block &block = boost::get<cryptonote::block>(e);
const uint64_t height = cryptonote::get_block_height(block);
if (!cryptonote::is_game_update_block(height))
continue;
const cryptonote::cc_command_game_update_t &cmd = boost::get<cryptonote::cc_command_game_update_t>(block.miner_tx.cc_cmd);
for (const auto &city: cmd.cities)
subsidy += city.subsidy;
}
return subsidy;
}
static bool expect_flag_tiles(cryptonote::core &c, uint32_t flag, const std::vector<std::vector<uint8_t>> &expected_tiles)
{
BlockchainDB &db = c.get_blockchain_storage().get_db();
cryptonote::cc_flag_data_t fd;
if (!db.get_cc_flag_data(flag, fd))
{
MERROR("Flag " << flag << " not found");
return false;
}
std::vector<std::vector<uint8_t>> tiles;
if (!cc::unpack_tiles(tiles, fd.tiles, fd.x1 - fd.x0 + 1, fd.y1 - fd.y0 + 1))
{
MERROR("Flag " << flag << " filed to unpack tiles");
return false;
}
if (tiles.size() != expected_tiles.size())
{
MERROR("Flag " << flag << " tiles aren't the expected size: " << tiles.size() << ", expected " << expected_tiles.size());
return false;
}
for (size_t i = 0; i < tiles.size(); ++i)
{
if (tiles[i] != expected_tiles[i])
{
MERROR("Flag " << flag << " has unexpected tiles at index " << i << ": " << tiles[i].size() << ", expected " << expected_tiles[i].size());
std::stringstream s;
for (const auto &e: tiles[i]) s << std::to_string(e) << " ";
MERROR(" actual tiles: " << s.str());
s = std::stringstream();
for (const auto &e: expected_tiles[i]) s << std::to_string(e) << " ";
MERROR(" expected tiles: " << s.str());
return false;
}
}
return true;
}
static bool expect_item_balances(cryptonote::core &c, uint32_t account, const std::vector<std::pair<uint32_t, uint32_t>> &expected_item_balances)
{
BlockchainDB &db = c.get_blockchain_storage().get_db();
cryptonote::cc_account_data_t data;
if (!db.get_cc_account_data(account, data))
{
MERROR("Failed to get item balances for account " << account);
return false;
}
for (uint32_t i = 0; i < NUM_PREDEFINED_ITEMS; ++i)
{
uint32_t expected_balance = 0;
for (const auto &e: expected_item_balances)
if (e.first == i)
expected_balance = e.second;
if (data.item_balances[i] != expected_balance)
{
MERROR("Unexpected " << cc::get_predefined_item_name(i) << " balance: " << data.item_balances[i] << ", expected " << expected_balance);
return false;
}
}
return true;
}
static crypto::public_key get_sample_pmspk()
{
static crypto::public_key k = crypto::null_pkey;
if (k == crypto::null_pkey)
k = rct::rct2pk(rct::scalarmultBase(rct::skGen()));
return k;
}
static crypto::public_key get_sample_pmvpk()
{
static crypto::public_key k = crypto::null_pkey;
if (k == crypto::null_pkey)
k = rct::rct2pk(rct::scalarmultBase(rct::skGen()));
return k;
}
//----------------------------------------------------------------------------------------------------------------------
// Tests
bool gen_cc_tx_validation_base::generate_game_update_command(cryptonote::core &c, size_t ev_index, const std::vector<test_event_entry> &events_)
{
std::vector<test_event_entry> &events = const_cast<std::vector<test_event_entry>&>(events_);
if (ev_index + 1 >= events.size())
{
MERROR("event index is out of range");
return false;
}
auto &e = events[ev_index + 1];
if (e.type() != typeid(cryptonote::block))
{
MERROR("Game update event is not a block");
return false;
}
game_events.clear();
cryptonote::cc_command_game_update_t cg = cc::create_cc_game_update_command(c.get_blockchain_storage().get_db(), BASE_TEST_FORK, game_events);
auto &b = boost::get<cryptonote::block>(e);
b.miner_tx.cc_cmd = cg;
return true;
}
bool gen_cc_tx_validation_base::generate_with_full(std::vector<test_event_entry>& events,
const boost::optional<cryptonote::cc_account_source> &cc_source, boost::optional<cryptonote::cc_account_dest> cc_dest,
preparation_t preparation, unsigned int n_txes, unsigned n_inputs, unsigned int mixin, uint64_t amount_paid,
bool bare, const std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> &bare_cmds,
bool pop_block, validity_t validity, bool update,
const std::function<bool(test_generator &generator, std::vector<test_event_entry> &events)> &generate_more,
const std::function<void(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations)> &pre_tx,
const std::function<void(transaction &tx)> &post_tx) const
{
uint64_t ts_start = 1338224400;
std::vector<block> blockchain;
auto miner_account = cc_test_accounts[0];
MAKE_CC_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
blockchain.push_back(blk_0);
for (size_t i = 0; i < sizeof(expected_balance) / sizeof(expected_balance[0]); ++i)
expected_balance[i] = 0;
expected_treasury_balance = 0;
// create 8 miner accounts, and have them mine the next 8 blocks
const cryptonote::block *prev_block = &blk_0;
cryptonote::block blocks[8];
for (size_t n = 0; n < 8; ++n) {
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, cc_test_accounts[n],
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
BASE_TEST_FORK, BASE_TEST_FORK, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, BASE_TEST_FORK),
false, "Failed to generate block");
events.push_back(blocks[n]);
prev_block = blocks + n;
blockchain.push_back(blocks[n]);
}
// rewind
cryptonote::block blk_last;
{
blk_last = *prev_block;
const size_t nblocks = CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW + mixin + (preparation == prep_large_balance ? N_LARGE_BALANCE_OUTS : preparation == prep_buy_stuff ? 8 : 0);
for (size_t i = 0; i < nblocks; ++i) // unlock enough blocks to have enough fake outs
{
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, BASE_TEST_FORK),
false, "Failed to generate block");
if (cryptonote::is_game_update_block(cryptonote::get_block_height(blk)))
{
blk.miner_tx.minor_version = 1;
DO_CALLBACK(events, "generate_game_update_command");
}
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
}
}
if (preparation != prep_none)
{
std::vector<crypto::hash> tx_hashes;
uint64_t tx_fees = 0;
for (size_t i = 0; i < 8; ++i)
{
// create a rct tx
std::vector<tx_source_entry> sources;
sources.resize(sources.size()+1);
tx_source_entry& src = sources.back();
src.real_output = i+1;
src.amount = blockchain[src.real_output].miner_tx.vout[0].amount;
src.real_out_tx_key = get_tx_pub_key_from_extra(blockchain[src.real_output].miner_tx);
src.real_output_in_tx_index = 0;
src.mask = rct::identity();
src.rct = true;
for (unsigned int m = 0; m <= mixin; ++m) {
rct::ctkey ctkey;
if (blockchain[m].miner_tx.vout[0].target.type() == typeid(txout_to_tagged_key))
ctkey.dest = rct::pk2rct(boost::get<txout_to_tagged_key>(blockchain[m].miner_tx.vout[0].target).key);
else
ctkey.dest = rct::pk2rct(boost::get<txout_to_key>(blockchain[m].miner_tx.vout[0].target).key);
ctkey.mask = rct::zeroCommit(blockchain[m].miner_tx.vout[0].amount);
src.outputs.push_back(std::make_pair(m, ctkey));
}
//fill outputs entry
tx_destination_entry td;
td.addr = miner_account.get_keys().m_account_address;
td.amount = 1;
std::vector<tx_destination_entry> destinations;
destinations.push_back(td);
// dummy output required from v12
td.addr = dummy_change_account.get_keys().m_account_address;
td.amount = 0;
destinations.push_back(td);
transaction tx;
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
const auto &sending_account = src.real_output > 0 && src.real_output <= 8 ? cc_test_accounts[src.real_output - 1] : miner_account;
subaddresses[sending_account.get_keys().m_account_address.m_spend_public_key] = {0,0};
const rct::RCTConfig rct_config = { rct::RangeProofPaddedBulletproof, 0 };
cc_account_dest cc_create_account_dest = {true, 0, cc::get_cc_public_key(sending_account.get_keys().m_spend_secret_key), CRYPTONOTE_CC_NEW_ACCOUNT_FEE + initial_funding[i], "House " + std::to_string(i), "player " + std::to_string(i), DEFAULT_AVATAR_SETTINGS, 0, get_sample_pmspk(), get_sample_pmvpk()};
expected_balance[i] += initial_funding[i];
expected_treasury_balance += CRYPTONOTE_CC_NEW_ACCOUNT_FEE - NEWBIE_COIN_GOLD_CONTENT;
bool r = construct_tx_and_get_tx_key(cryptonote::FAKECHAIN, sending_account.get_keys(), subaddresses, sources, boost::none, destinations, cc_create_account_dest, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, tx_key, additional_tx_keys, true, rct_config, true, BASE_TEST_FORK);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
tx_hashes.push_back(get_transaction_hash(tx));
tx_fees += cryptonote::get_tx_fee(tx);
events.push_back(tx);
}
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_tx_hashes | test_generator::bf_tx_fees,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), tx_hashes, 0, 0, BASE_TEST_FORK, tx_fees),
false, "Failed to generate block");
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
}
if (preparation == prep_large_balance || preparation == prep_buy_stuff)
{
// send lots of balance to an account
std::vector<tx_source_entry> sources;
const size_t n_outs = preparation == prep_large_balance ? N_LARGE_BALANCE_OUTS : 8;
size_t n_outs_this_time = 0;
uint64_t tx_fees = 0;
std::vector<crypto::hash> tx_hashes;
for (size_t i = 0; i < n_outs; ++i)
{
sources.resize(sources.size()+1);
tx_source_entry& src = sources.back();
src.real_output = 9;
src.amount = blockchain[src.real_output+i].miner_tx.vout[0].amount;
src.real_out_tx_key = get_tx_pub_key_from_extra(blockchain[src.real_output+i].miner_tx);
src.real_output_in_tx_index = 0;
src.mask = rct::identity();
src.rct = true;
for (unsigned int m = 0; m <= mixin; ++m) {
rct::ctkey ctkey;
if (blockchain[m+i].miner_tx.vout[0].target.type() == typeid(txout_to_tagged_key))
ctkey.dest = rct::pk2rct(boost::get<txout_to_tagged_key>(blockchain[m+i].miner_tx.vout[0].target).key);
else
ctkey.dest = rct::pk2rct(boost::get<txout_to_key>(blockchain[m+i].miner_tx.vout[0].target).key);
ctkey.mask = rct::zeroCommit(blockchain[m+i].miner_tx.vout[0].amount);
src.outputs.push_back(std::make_pair(m+i, ctkey));
}
++n_outs_this_time;
if (n_outs_this_time == 128 || i == n_outs - 1)
{
//fill outputs entry
tx_destination_entry td;
td.addr = miner_account.get_keys().m_account_address;
td.amount = 1;
std::vector<tx_destination_entry> destinations;
destinations.push_back(td);
// dummy output required from v12
td.addr = dummy_change_account.get_keys().m_account_address;
td.amount = 0;
destinations.push_back(td);
transaction tx;
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
const auto &sending_account = miner_account;
subaddresses[sending_account.get_keys().m_account_address.m_spend_public_key] = {0,0};
const rct::RCTConfig rct_config = { rct::RangeProofPaddedBulletproof, 0 };
const int dest_idx = preparation == prep_large_balance ? 3 : 0;
cc_account_dest cc_account_dest = {false, 0, cc::get_cc_public_key(cc_test_accounts[dest_idx].get_keys().m_spend_secret_key), n_outs_this_time * 17*COIN, "", "", DEFAULT_AVATAR_SETTINGS, 0, get_sample_pmspk(), get_sample_pmvpk(), 0};
expected_balance[dest_idx] += cc_account_dest.amount;
bool r = construct_tx_and_get_tx_key(cryptonote::FAKECHAIN, sending_account.get_keys(), subaddresses, sources, boost::none, destinations, cc_account_dest, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, tx_key, additional_tx_keys, true, rct_config, true, BASE_TEST_FORK);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
tx_hashes.push_back(cryptonote::get_transaction_hash(tx));
tx_fees += cryptonote::get_tx_fee(tx);
events.push_back(tx);
n_outs_this_time = 0;
sources.clear();
}
}
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_tx_hashes | test_generator::bf_tx_fees,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), tx_hashes, 0, 0, BASE_TEST_FORK, tx_fees),
false, "Failed to generate block");
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
}
if (preparation == prep_buy_stuff)
{
std::vector<crypto::hash> txs_hashes;
const uint32_t cc_account = FIRST_TEST_ACCOUNT;
transaction tx;
uint64_t fee = 0, tx_fees = 0;
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_nonce = 4000;
buy_land.cc_account = cc_account;
buy_land.city = 0;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
buy_land.x = ox + PREP_BUY_LAND_X;
buy_land.y = oy + PREP_BUY_LAND_Y;
buy_land.wm1 = PREP_BUY_LAND_WM1;
buy_land.hm1 = PREP_BUY_LAND_HM1;
uint64_t cost;
if (!cc::get_new_flag_cost(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, cost))
return false;
fee = BARE_TX_FEE;
tx_fees += fee;
const auto &sending_account = cc_test_accounts[cc_account - FIRST_TEST_ACCOUNT];
CHECK_AND_ASSERT_MES(cost + fee <= expected_balance[cc_account - FIRST_TEST_ACCOUNT], false, "Underflow");
expected_balance[cc_account - FIRST_TEST_ACCOUNT] -= cost + fee;
expected_treasury_balance += cost;
bool r = construct_bare_tx(cryptonote::FAKECHAIN, sending_account.get_keys(), buy_land, fee, BASE_TEST_FORK, tx);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
events.push_back(tx);
txs_hashes.push_back(get_transaction_hash(tx));
cryptonote::cc_command_buy_items_t buy_blocks;
buy_blocks.cc_account = cc_account;
static const uint32_t buy_amounts[] = { ITEM_BASIC_STONE, STARTING_BLOCK_1, ITEM_BASIC_WOOD, STARTING_BLOCK_2, ITEM_LABOUR, STARTING_LABOUR };
for (size_t i = 0; i < sizeof(buy_amounts) / sizeof(buy_amounts[0]); i += 2)
{
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = buy_amounts[i];
e.amount = buy_amounts[i + 1];
buy_blocks.entries.push_back(e);
CHECK_AND_ASSERT_MES(cc::get_last_resort_price(e.type) * e.amount + fee <= expected_balance[cc_account - FIRST_TEST_ACCOUNT], false, "Underflow");
expected_balance[cc_account - FIRST_TEST_ACCOUNT] -= cc::get_last_resort_price(e.type) * e.amount;
expected_treasury_balance += cc::get_last_resort_price(e.type) * e.amount;
}
fee = BARE_TX_FEE;
tx_fees += fee;
expected_balance[cc_account - FIRST_TEST_ACCOUNT] -= fee;
r = construct_bare_tx(cryptonote::FAKECHAIN, sending_account.get_keys(), buy_blocks, fee, BASE_TEST_FORK, tx);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
events.push_back(tx);
txs_hashes.push_back(get_transaction_hash(tx));
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_tx_hashes | test_generator::bf_tx_fees,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), txs_hashes, 0, 0, BASE_TEST_FORK, tx_fees),
false, "Failed to generate block");
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
}
crypto::hash last_tx_hash;
uint64_t tx_fee = 0;
unsigned input_idx = 0;
for (unsigned i = 0; i < n_txes; ++i)
{
if (i == n_txes - 1 && update)
{
while (1)
{
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, BASE_TEST_FORK),
false, "Failed to generate block");
if (cryptonote::is_game_update_block(cryptonote::get_block_height(blk)))
{
blk.miner_tx.minor_version = 1;
DO_CALLBACK(events, "generate_game_update_command");
}
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
if (cryptonote::is_game_update_block(cryptonote::get_block_height(blk)))
break;
}
}
transaction tx;
if (bare)
{
uint64_t fee = 0;
cryptonote::cc_command_t cmd;
cryptonote::cc_command_transfer_t transfer;
if (i < bare_cmds.size())
{
cmd = std::get<1>(bare_cmds[i]);
fee = std::get<2>(bare_cmds[i]);
if (!std::get<0>(bare_cmds[i]).empty())
DO_CALLBACK(events, std::get<0>(bare_cmds[i]));
}
else
{
transfer.cc_account = FIRST_TEST_ACCOUNT;
transfer.in_amount = cc_source ? cc_source->amount : 0;
transfer.public_key = cc_dest ? cc_dest->public_key : crypto::null_pkey;
transfer.out_amount = cc_dest ? cc_dest->amount : 0;
cmd = transfer;
fee = BARE_TX_FEE;
}
const cryptonote::cc_command_base_t *base = cryptonote::get_cc_command_base(cmd);
CHECK_AND_ASSERT_MES(base, false, "Command base not found");
const auto &sending_account = cc_test_accounts[base->cc_account - FIRST_TEST_ACCOUNT];
bool r = construct_bare_tx(cryptonote::FAKECHAIN, sending_account.get_keys(), cmd, fee, BASE_TEST_FORK, tx);
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
tx_fee += fee;
}
else
{
// create a rct tx
std::vector<tx_source_entry> sources;
for (unsigned int j = 0; j < n_inputs; ++j, ++input_idx)
{
sources.resize(sources.size()+1);
tx_source_entry& src = sources.back();
unsigned int output_to_send = input_idx == 0 ? 0 : (input_idx+9);
src.real_output = output_to_send;
src.amount = blockchain[src.real_output].miner_tx.vout[0].amount;
src.real_out_tx_key = get_tx_pub_key_from_extra(blockchain[src.real_output].miner_tx);
src.real_output_in_tx_index = 0;
src.mask = rct::identity();
src.rct = true;
for (unsigned int m = 0; m <= mixin; ++m) {
rct::ctkey ctkey;
ctkey.dest = rct::pk2rct(boost::get<txout_to_tagged_key>(blockchain[m].miner_tx.vout[0].target).key);
ctkey.mask = rct::zeroCommit(blockchain[m].miner_tx.vout[0].amount);
src.outputs.push_back(std::make_pair(m, ctkey));
}
}
//fill outputs entry
tx_destination_entry td;
td.addr = miner_account.get_keys().m_account_address;
td.amount = amount_paid;
std::vector<tx_destination_entry> destinations;
destinations.push_back(td);
// dummy output required from v12
td.addr = dummy_change_account.get_keys().m_account_address;
td.amount = 0;
destinations.push_back(td);
if (pre_tx)
pre_tx(sources, destinations);
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
const auto &sending_account = sources[0].real_output > 0 && sources[0].real_output <= 8 ? cc_test_accounts[sources[0].real_output - 1] : miner_account;
subaddresses[sending_account.get_keys().m_account_address.m_spend_public_key] = {0,0};
const rct::RCTConfig rct_config = { rct::RangeProofPaddedBulletproof, 0 };
bool r = construct_tx_and_get_tx_key(cryptonote::FAKECHAIN, sending_account.get_keys(), subaddresses, sources, cc_source, destinations, cc_dest, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, tx_key, additional_tx_keys, true, rct_config, true, BASE_TEST_FORK);
if (!r && validity == invalid_on_creation)
{
DO_CALLBACK(events, "mark_check_final_state");
return true;
}
CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction");
tx_fee += tx.rct_signatures.txnFee;
}
if (post_tx)
post_tx(tx);
if (validity == invalid && i == n_txes-1)
DO_CALLBACK(events, "mark_invalid_tx");
events.push_back(tx);
last_tx_hash = get_transaction_hash(tx);
LOG_PRINT_L0("Test tx: " << obj_to_json_str(tx));
if (i+1 < n_txes)
{
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_tx_hashes | test_generator::bf_tx_fees,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(1, last_tx_hash), 0, 0, BASE_TEST_FORK, tx_fee),
false, "Failed to generate block");
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
tx_fee = 0;
}
}
if (validity == valid || validity == invalid_on_block)
{
// include the tx in a block so its actions get executed
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_tx_hashes | test_generator::bf_tx_fees,
BASE_TEST_FORK, BASE_TEST_FORK, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(1, last_tx_hash), 0, 0, BASE_TEST_FORK, tx_fee),
false, "Failed to generate block");
if (validity == invalid_on_block)
DO_CALLBACK(events, "mark_invalid_block");
events.push_back(blk);
blk_last = blk;
blockchain.push_back(blk);
if (pop_block)
events.push_back(pop_blocks(1));
DO_CALLBACK(events, "mark_check_final_state");
}
if (generate_more)
if (!generate_more(generator, events))
return false;
return true;
}
bool gen_cc_tx_validation_base::generate_with(std::vector<test_event_entry>& events,
const boost::optional<cryptonote::cc_account_source> &cc_source, boost::optional<cryptonote::cc_account_dest> cc_dest,
preparation_t preparation, unsigned int n_txes, unsigned int mixin, uint64_t amount_paid,
bool bare, const std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> &bare_cmds,
bool pop_block, validity_t validity,
const std::function<void(std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations)> &pre_tx,
const std::function<void(transaction &tx)> &post_tx) const
{
return generate_with_full(events, cc_source, cc_dest, preparation, n_txes, 1, mixin, amount_paid, bare, bare_cmds, pop_block, validity, false, NULL, pre_tx, post_tx);
}
bool gen_cc_tx_valid_non_cc::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
return generate_with(events, boost::none, boost::none, prep_none, 1, mixin, amount_paid, false, {}, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_non_cc::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_treasury_balance(c, 0);
}
bool gen_cc_tx_valid_create_account::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
CRYPTONOTE_CC_NEW_ACCOUNT_FEE,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, boost::none, dest, prep_none, 1, mixin, amount_paid, false, {}, false, valid, NULL, [](cryptonote::transaction &tx) {
const crypto::public_key pkey = cc_test_accounts[7].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[7].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
});
}
bool gen_cc_tx_valid_create_account::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT, 0) && expect_treasury_balance(c, CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_invalid_create_account_low_fee::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
CRYPTONOTE_CC_NEW_ACCOUNT_FEE - 1,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, boost::none, dest, prep_none, 1, mixin, amount_paid, false, {}, false, invalid, NULL, [](cryptonote::transaction &tx) {
const crypto::public_key pkey = cc_test_accounts[7].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[7].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
});
}
bool gen_cc_tx_valid_create_account_including_deposit::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
CRYPTONOTE_CC_NEW_ACCOUNT_FEE + 42,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, boost::none, dest, prep_none, 1, mixin, amount_paid, false, {}, false, valid, NULL, [](cryptonote::transaction &tx) {
const crypto::public_key pkey = cc_test_accounts[7].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[7].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
});
}
bool gen_cc_tx_valid_create_account_including_deposit::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT, 42) && expect_treasury_balance(c, CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_invalid_cc_one_in_no_out_invalid_cc_account::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {8, crypto::null_pkey, 1};
return generate_with(events, source, boost::none, prep_none, 1, mixin, amount_paid, false, {}, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_one_in_one_out_invalid_cc_account::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {8, crypto::null_pkey, 1};
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
CRYPTONOTE_CC_NEW_ACCOUNT_FEE,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_none, 1, mixin, amount_paid, false, {}, false, invalid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_4_accounts::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
return generate_with(events, boost::none, boost::none, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_4_accounts::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0])
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_valid_cc_one_in_one_out::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
5000,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_one_in_one_out::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0] - 1)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1] + 5000)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_invalid_cc_one_in_one_out_more_than_inputs::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 17*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
1*COIN,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
if (generate_with(events, source, dest, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, invalid, NULL, NULL))
return false;
return true;
}
bool gen_cc_tx_valid_cc_one_in_one_out_more_than_rct_inputs_but_balance_is_large_enough::generate(std::vector<test_event_entry>& events) const
{
// input: 30 from game, 35 from rct
// output: 1, 50
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 15*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
30*COIN,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_large_balance, 1, mixin, amount_paid, false, {}, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_one_in_one_out_more_than_rct_inputs_but_balance_is_large_enough::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
uint64_t subsidy = get_subsidy_total(c, events);
subsidy -= subsidy * MAYOR_PAYOUT + subsidy * GAME_PAYOUT;
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0] - 15*COIN)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1] + 30*COIN)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3] + N_LARGE_BALANCE_OUTS*17*COIN) // from the large amount prep
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD + subsidy);
}
bool gen_cc_tx_invalid_cc_one_in_one_out_more_than_rct_inputs_but_balance_is_not_large_enough::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 40*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
50*COIN,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_large_balance, 1, mixin, amount_paid, false, {}, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_multiple_txes_spend_more_than_balance::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 15*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
5000,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_create_accounts, 2, mixin, amount_paid, false, {}, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bad_signature::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
5000,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, invalid, NULL, [](transaction &tx) {
const auto &sender_account_keys = cc_test_accounts[0].get_keys();
cc::generate_signature(crypto::null_hash, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
});
}
bool gen_cc_tx_invalid_cc_signature_by_wrong_keys::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
false,
0,
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
5000,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, invalid, NULL, [](transaction &tx) {
const auto &sender_account_keys = cc_test_accounts[7].get_keys();
const crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
cc::generate_signature(tx_prefix_hash, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
});
}
bool gen_cc_tx_valid_cc_one_in_no_out::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 16*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
return generate_with(events, source, boost::none, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_one_in_no_out::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0] - 16*COIN)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_valid_cc_pop_reverts::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 1*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 16*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
return generate_with(events, source, boost::none, prep_create_accounts, 1, mixin, amount_paid, false, {}, true, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_pop_reverts::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0])
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_invalid_cc_bare_one_in_no_out::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
return generate_with(events, source, boost::none, prep_create_accounts, 1, mixin, amount_paid, true, {}, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_no_in_one_out::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[3].get_keys().m_spend_secret_key),
1,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, boost::none, dest, prep_create_accounts, 1, mixin, amount_paid, true, {}, false, invalid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_one_in_one_out::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1234567890}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[3].get_keys().m_spend_secret_key),
1234567890,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_create_accounts, 1, mixin, amount_paid, true, {}, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_one_in_one_out::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0] - 1234567890 - BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3] + 1234567890)
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD);
}
bool gen_cc_tx_invalid_cc_bare_transfer_whole_balance_nothing_left_for_fee::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
uint64_t balance = 34*COIN;
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, balance}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
const cryptonote::cc_account_dest dest = {
true,
0,
cc::get_cc_public_key(cc_test_accounts[3].get_keys().m_spend_secret_key),
balance,
"test house",
"test name",
DEFAULT_AVATAR_SETTINGS,
0,
get_sample_pmspk(),
get_sample_pmvpk(),
0
};
return generate_with(events, source, dest, prep_create_accounts, 1, mixin, amount_paid, true, {}, false, invalid, NULL, NULL);
}
uint64_t gen_cc_tx_valid_cc_bare_buy_land_min_size::land_cost = 0;
bool gen_cc_tx_valid_cc_bare_buy_land_min_size::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_land_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.city = 0;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cmd.x = ox + 100;
cmd.y = oy + 200;
cmd.wm1 = 11;
cmd.hm1 = 11;
if (!cc::get_new_flag_cost(cmd.x, cmd.y, cmd.x + cmd.wm1, cmd.y + cmd.hm1, ox, oy, land_cost))
return false;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, 1, mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_buy_land_min_size::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0] - land_cost - BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD + land_cost);
}
uint64_t gen_cc_tx_valid_cc_bare_buy_land_max_size::land_cost = 0;
bool gen_cc_tx_valid_cc_bare_buy_land_max_size::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_transfer_t transfer;
transfer.cc_account = FIRST_TEST_ACCOUNT + 1;
transfer.in_amount = 15*COIN;
transfer.public_key = cc::get_cc_public_key(cc_test_accounts[0].get_keys().m_spend_secret_key);
transfer.out_amount = 15*COIN;
cmds.push_back(std::make_tuple("", transfer, BARE_TX_FEE));
transfer.cc_account = FIRST_TEST_ACCOUNT + 2;
transfer.in_amount = 15*COIN;
transfer.public_key = cc::get_cc_public_key(cc_test_accounts[0].get_keys().m_spend_secret_key);
transfer.out_amount = 15*COIN;
cmds.push_back(std::make_tuple("", transfer, BARE_TX_FEE));
transfer.cc_account = FIRST_TEST_ACCOUNT + 4;
transfer.in_amount = 15*COIN;
transfer.public_key = cc::get_cc_public_key(cc_test_accounts[0].get_keys().m_spend_secret_key);
transfer.out_amount = 15*COIN;
cmds.push_back(std::make_tuple("", transfer, BARE_TX_FEE));
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT + 3;
cmd.city = 0;
cmd.x = ox + 100;
cmd.y = oy + 200;
cmd.wm1 = 255;
cmd.hm1 = 255;
if (!cc::get_new_flag_cost(cmd.x, cmd.y, cmd.x + cmd.wm1, cmd.y + cmd.hm1, ox, oy, land_cost))
return false;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_large_balance, 4, mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_buy_land_max_size::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
uint64_t subsidy = get_subsidy_total(c, events);
subsidy -= subsidy * MAYOR_PAYOUT + subsidy * GAME_PAYOUT;
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, initial_funding[0] + 3 * 15*COIN)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, initial_funding[1] - 15*COIN - BARE_TX_FEE)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, initial_funding[2] - 15*COIN - BARE_TX_FEE)
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, initial_funding[3] + N_LARGE_BALANCE_OUTS * 17 * COIN - land_cost - BARE_TX_FEE)
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4] - 15*COIN - BARE_TX_FEE)
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, 8 * CRYPTONOTE_CC_NEW_ACCOUNT_FEE_MINUS_NEWBIE_COIN_GOLD + land_cost + subsidy);
}
bool gen_cc_tx_invalid_cc_bare_buy_land_too_small::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint64_t cost;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.city = 0;
cmd.x = ox + 100;
cmd.y = ox + 200;
cmd.wm1 = MIN_BUY_SIDE_SIZE - 2;
cmd.hm1 = MIN_BUY_SIDE_SIZE - 2;
if (!cc::get_new_flag_cost(cmd.x, cmd.y, cmd.x + cmd.wm1, cmd.y + cmd.hm1, ox, oy, cost))
return false;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, 1, mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_buy_land_not_enough_balance::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint64_t cost;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT + 3;
cmd.city = 0;
cmd.x = ox + 100;
cmd.y = oy + 200;
cmd.wm1 = 255;
cmd.hm1 = 255;
if (!cc::get_new_flag_cost(cmd.x, cmd.y, cmd.x + cmd.wm1, cmd.y + cmd.hm1, ox, oy, cost))
return false;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, 1, mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_buy_land_overlapping::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_land_t cmd;
uint64_t cost;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.city = 0;
cmd.x = ox + 134;
cmd.y = oy + 134;
cmd.wm1 = 11;
cmd.hm1 = 11;
if (!cc::get_new_flag_cost(cmd.x, cmd.y, cmd.x + cmd.wm1, cmd.y + cmd.hm1, ox, oy, cost))
return false;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
cmd.cc_account = FIRST_TEST_ACCOUNT + 1;
cmd.city = 0;
cmd.x = ox + 133;
cmd.y = oy + 134;
cmd.wm1 = 6;
cmd.hm1 = 4;
if (!cc::get_new_flag_cost(cmd.x, cmd.y, cmd.x + cmd.wm1, cmd.y + cmd.hm1, ox, oy, cost))
return false;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, 2, mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_build_whole_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
// build a checker pattern
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_assign_items_t assign;
assign.cc_account = FIRST_TEST_ACCOUNT;
assign.flag = 1 + PREDEFINED_BUILDINGS;
assign.items.push_back({ITEM_BASIC_STONE, 20});
assign.items.push_back({ITEM_BASIC_WOOD, 30});
cmds.push_back(std::make_tuple("", assign, BARE_TX_FEE));
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 0;
cmd.dy = 0;
cmd.wm1 = 3;
cmd.hm1 = 3;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 16-1, 0, S, 0, S, 0, S, 0, S, 0, S, 0, S, 0, S, 0, S };
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_build_whole_flag::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 3 * BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_flag_tiles(c, 1 + PREDEFINED_BUILDINGS, { {}, {1}, {}, {1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {1}, {}, {1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {1}, {}, {1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {1}, {}, {1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} });
}
bool gen_cc_tx_valid_cc_bare_build_part_of_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_assign_items_t assign;
assign.cc_account = FIRST_TEST_ACCOUNT;
assign.flag = 1 + PREDEFINED_BUILDINGS;
assign.items.push_back({ITEM_BASIC_STONE, 20});
assign.items.push_back({ITEM_BASIC_WOOD, 30});
cmds.push_back(std::make_tuple("", assign, BARE_TX_FEE));
// build a checker pattern
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 1;
cmd.dy = 2;
cmd.wm1 = 1;
cmd.hm1 = 1;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 4-1, 0, S, 0, S };
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_build_part_of_flag::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 3 * BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_flag_tiles(c, 1 + PREDEFINED_BUILDINGS, {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} });
}
bool gen_cc_tx_invalid_cc_bare_build_out_of_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 1;
cmd.dy = 12 - 3;
cmd.wm1 = 0;
cmd.hm1 = 5;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 6-1, 0, S, 0, S, 0, S };
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_build_invalid_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 20;
cmd.dx = 1;
cmd.dy = 2;
cmd.wm1 = 1;
cmd.hm1 = 1;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 4-1, 0, S, 0, S };
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_build_not_owned::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT + 1;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 1;
cmd.dy = 2;
cmd.wm1 = 1;
cmd.hm1 = 1;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 4-1, 0, S, 0, S };
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, 1, mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_build_too_long_decoded_block_data::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 1;
cmd.dy = 2;
cmd.wm1 = 1;
cmd.hm1 = 1;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 5-1, 0, S, 0, S, 0 };
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_build_stacked::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_assign_items_t assign;
assign.cc_account = FIRST_TEST_ACCOUNT;
assign.flag = 1 + PREDEFINED_BUILDINGS;
assign.items.push_back({ITEM_BASIC_STONE, 20});
assign.items.push_back({ITEM_BASIC_WOOD, 30});
cmds.push_back(std::make_tuple("", assign, BARE_TX_FEE));
// build a checker pattern
cryptonote::cc_command_build_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 1;
cmd.dy = 2;
cmd.wm1 = 1;
cmd.hm1 = 1;
cmd.height = 0;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t W = ITEM_BASIC_WOOD;
static const uint8_t block_data0[] = { 4-1, 0, S, 0, S };
cmd.block_data = std::vector<uint8_t>(block_data0, block_data0 + sizeof(block_data0));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
// build on top of some of them
static const uint8_t block_data1[] = { 4-1, S, 0, 0, 0 };
cmd.block_data = std::vector<uint8_t>(block_data1, block_data1 + sizeof(block_data1));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
static const uint8_t block_data2[] = { 4-1, 0, 0, W, 0 };
cmd.block_data = std::vector<uint8_t>(block_data2, block_data2 + sizeof(block_data2));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
// build on top of others
cmd.height = 1;
static const uint8_t block_data3[] = { 4-1, S, S, 0, W};
cmd.block_data = std::vector<uint8_t>(block_data3, block_data3 + sizeof(block_data3));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
cmd.dy = 1;
static const uint8_t block_data4[] = { 4-1, S, S, 0, 0};
cmd.block_data = std::vector<uint8_t>(block_data4, block_data4 + sizeof(block_data4));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
// build on another overlapping area
cmd.height = 2;
cmd.dx = 0;
static const uint8_t block_data5[] = { 4-1, 0, S, S, S };
cmd.block_data = std::vector<uint8_t>(block_data5, block_data5 + sizeof(block_data5));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
// build under existing geometry
cmd.height = 1;
static const uint8_t block_data6[] = { 4-1, W, 0, W, 0 };
cmd.block_data = std::vector<uint8_t>(block_data6, block_data6 + sizeof(block_data6));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_build_stacked::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t W = ITEM_BASIC_WOOD;
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 9 * BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_flag_tiles(c, 1 + PREDEFINED_BUILDINGS,
{ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{0,W}, {0,S,S}, {0,S}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{0,W,S}, {S,S,S}, {S,S}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {W}, {S,W}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} });
}
bool gen_cc_tx_invalid_cc_bare_build_not_enough_blocks::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_build_t cmd;
for (int i = 0; i < 23; ++i)
{
cmd.cc_account = FIRST_TEST_ACCOUNT;
cmd.flag = 1 + PREDEFINED_BUILDINGS;
cmd.dx = 0;
cmd.dy = 0;
cmd.wm1 = 5;
cmd.hm1 = 4;
cmd.height = i;
cmd.remove = false;
static const uint8_t S = ITEM_BASIC_STONE;
static const uint8_t block_data[] = { 30-1, S, S, S, S, S, S, S, S, S, S, S, S, S, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cmd.block_data = std::vector<uint8_t>(block_data, block_data + sizeof(block_data));
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
}
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
uint64_t gen_cc_tx_valid_cc_bare_buy_blocks::blocks_cost = 0;
bool gen_cc_tx_valid_cc_bare_buy_blocks::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
blocks_cost = 0;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 8;
cmd.entries.push_back(e);
blocks_cost += cc::get_last_resort_price(e.type) * e.amount;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
e.type = ITEM_BASIC_WOOD;
e.amount = 18;
cmd.entries[0] = e;
blocks_cost += cc::get_last_resort_price(e.type) * e.amount;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
e.type = ITEM_BASIC_STONE;
e.amount = 4;
cmd.entries[0] = e;
blocks_cost += cc::get_last_resort_price(e.type) * e.amount;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_buy_blocks::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - blocks_cost - 3 * BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance + blocks_cost)
&& expect_item_balances(c, FIRST_TEST_ACCOUNT, {std::make_pair(ITEM_BASIC_STONE, 12), std::make_pair(ITEM_BASIC_WOOD, 18)});
}
bool gen_cc_tx_invalid_cc_bare_buy_blocks_type_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = 0;
e.amount = 1;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_buy_blocks_amount_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 0;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_buy_blocks_balance_overflow::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 0x1fffffff;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_buy_blocks_balance_overflow_in_aggregate::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 30000000;
cmd.entries.push_back(e);
e.type = ITEM_BASIC_WOOD;
e.amount = 30000000;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_buy_blocks_duplicate_type::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 0x100;
cmd.entries.push_back(e);
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_create_accounts, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_trade_bid_blocks::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_trade_bid_blocks::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance);
}
bool gen_cc_tx_valid_cc_bare_trade_offer_blocks::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_trade_offer_blocks::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance);
}
bool gen_cc_tx_invalid_cc_bare_trade_bid_invalid_type::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = 0xffffff;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_trade_bid_block_id_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = 0;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_trade_bid_invalid_block_id::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = NUM_ITEMS;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_trade_bid_expired::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = 10;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_trade_bid_not_enough_money::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 1;
trade.price = (uint64_t)1000*COIN;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_trade_bid_amount_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 0;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_trade_offer_amount_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 0;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_match_blocks_matching_amounts::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.bid = false;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.bid = true;
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = trade.amount * trade.price;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 20});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_valid_cc_bare_match_blocks_matching_amounts::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE + 20 * 1000)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] - 1 * BARE_TX_FEE - 20 * 1000)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_item_balances(c, FIRST_TEST_ACCOUNT, {std::make_pair(ITEM_BASIC_STONE, STARTING_BLOCK_1 - 20), std::make_pair(ITEM_BASIC_WOOD, STARTING_BLOCK_2), std::make_pair(ITEM_LABOUR, STARTING_LABOUR)})
&& expect_item_balances(c, FIRST_TEST_ACCOUNT + 1, {std::make_pair(ITEM_BASIC_STONE, 20)});
}
bool gen_cc_tx_valid_cc_bare_match_blocks_partial_buy::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.bid = false;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.bid = true;
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 12;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 12 * trade.price;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 12});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_valid_cc_bare_match_blocks_partial_buy::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE + 12 * 1000)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] - 1 * BARE_TX_FEE - 12 * 1000)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_item_balances(c, FIRST_TEST_ACCOUNT, {std::make_pair(ITEM_BASIC_STONE, STARTING_BLOCK_1 - 12), std::make_pair(ITEM_BASIC_WOOD, STARTING_BLOCK_2), std::make_pair(ITEM_LABOUR, STARTING_LABOUR)})
&& expect_item_balances(c, FIRST_TEST_ACCOUNT + 1, {std::make_pair(ITEM_BASIC_STONE, 12)});
}
bool gen_cc_tx_valid_cc_bare_match_blocks_partial_sell::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 25;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 20 * trade.price;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 20});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_valid_cc_bare_match_blocks_partial_sell::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE + 20 * 1000)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] - 1 * BARE_TX_FEE - 20 * 1000)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_item_balances(c, FIRST_TEST_ACCOUNT, {std::make_pair(ITEM_BASIC_STONE, STARTING_BLOCK_1 - 20), std::make_pair(ITEM_BASIC_WOOD, STARTING_BLOCK_2), std::make_pair(ITEM_LABOUR, STARTING_LABOUR)})
&& expect_item_balances(c, FIRST_TEST_ACCOUNT + 1, {std::make_pair(ITEM_BASIC_STONE, 20)});
}
bool gen_cc_tx_invalid_cc_bare_match_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual_price_limit = 0;
trade.accrual = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = trade.amount * trade.price;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 0});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_invalid_cc_bare_match_more_than_trade::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = trade.amount * trade.price;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 25});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_invalid_cc_bare_trade_from_account_0::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [](transaction &tx) {
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_account = 0;
});
}
bool gen_cc_tx_invalid_cc_bare_match_non_trade_tx::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_land_t buy_land;
cryptonote::cc_command_trade_t trade;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 200;
buy_land.y = oy + 20;
buy_land.wm1 = 11;
buy_land.hm1 = 11;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_buy_land_t))
{
matches.push_back({boost::get<cryptonote::cc_command_buy_land_t>(tx.cc_cmd).cc_nonce, 1});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_invalid_cc_bare_match_duplicate_trade_tx::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 40;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [&](transaction &tx) {
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 20});
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 20});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_valid_cc_bare_match_two_buys_from_one_sell::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 15;
trade.price = 1020;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 15 * 1000;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 2;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 5;
trade.price = 1050;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 5 * 1000;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
uint32_t idx = 0;
uint64_t offer_nonce = 0;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, [&](transaction &tx) {
++idx;
switch (idx)
{
case 1:
offer_nonce = boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce;
break;
case 2:
case 3:
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches.push_back({offer_nonce, 15 - 10 * (idx-2)});
const auto &sender_account_keys = cc_test_accounts[idx-1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
break;
}
}
});
}
bool gen_cc_tx_valid_cc_bare_match_two_buys_from_one_sell::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE + 20 * 1000)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] - 1 * BARE_TX_FEE - 15 * 1000)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2] - 1 * BARE_TX_FEE - 5 * 1000)
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance)
&& expect_item_balances(c, FIRST_TEST_ACCOUNT, {std::make_pair(ITEM_BASIC_STONE, STARTING_BLOCK_1 - 20), std::make_pair(ITEM_BASIC_WOOD, STARTING_BLOCK_2), std::make_pair(ITEM_LABOUR, STARTING_LABOUR)})
&& expect_item_balances(c, FIRST_TEST_ACCOUNT + 1, {std::make_pair(ITEM_BASIC_STONE, 15)})
&& expect_item_balances(c, FIRST_TEST_ACCOUNT + 2, {std::make_pair(ITEM_BASIC_STONE, 5)});
}
bool gen_cc_tx_valid_cc_bare_maker_no_fee::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.bid = false;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, 0));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_taker_no_fee::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_trade_t trade;
trade.bid = false;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
trade.bid = true;
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.type = cryptonote::cc_command_trade_t::type_item;
trade.id = ITEM_BASIC_STONE;
trade.amount = 20;
trade.price = 1000;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = trade.amount * trade.price;
cmds.push_back(std::make_tuple("", trade, 0));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 20});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
uint64_t gen_cc_tx_valid_cc_bare_trade_flag::land_cost = 0;
uint64_t gen_cc_tx_valid_cc_bare_trade_flag::blocks_cost = 0;
bool gen_cc_tx_valid_cc_bare_trade_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
land_cost = 0;
blocks_cost = 0;
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 240;
buy_land.y = oy + 20;
buy_land.wm1 = 63;
buy_land.hm1 = 63;
if (!cc::get_new_flag_cost(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, land_cost))
return false;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1700;
cmd.entries.push_back(e);
blocks_cost += cc::get_last_resort_price(e.type) * e.amount;
e.type = ITEM_BASIC_WOOD;
e.amount = 3800;
cmd.entries.push_back(e);
blocks_cost += cc::get_last_resort_price(e.type) * e.amount;
e.type = ITEM_LABOUR;
e.amount = 31500;
cmd.entries.push_back(e);
blocks_cost += cc::get_last_resort_price(e.type) * e.amount;
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 2 + PREDEFINED_BUILDINGS;
settings.role = ROLE_AGRICULTURAL;
settings.economic_power = 100;
settings.construction_height = 80 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_flag;
trade.id = 2 + PREDEFINED_BUILDINGS;
trade.amount = 1;
trade.price = 10 * COIN;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
const uint64_t construction_height = 82 + mixin; // brittle
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_flag;
trade.id = 2 + PREDEFINED_BUILDINGS;
trade.amount = 1;
trade.price = 10 * COIN;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = construction_height;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 10 * COIN;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 1});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
bool gen_cc_tx_valid_cc_bare_trade_flag::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 4 * BARE_TX_FEE - land_cost - blocks_cost + 10 * COIN)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] - 10 * COIN - BARE_TX_FEE)
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance + land_cost + blocks_cost);
}
bool gen_cc_tx_invalid_cc_bare_trade_flag_build_destroyed::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 240;
buy_land.y = oy + 20;
buy_land.wm1 = 63;
buy_land.hm1 = 63;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1700;
cmd.entries.push_back(e);
e.type = ITEM_BASIC_WOOD;
e.amount = 3800;
cmd.entries.push_back(e);
e.type = ITEM_LABOUR;
e.amount = 31500;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 2 + PREDEFINED_BUILDINGS;
settings.role = ROLE_AGRICULTURAL;
settings.economic_power = 100;
settings.construction_height = 80 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_trade_t trade;
trade.cc_account = FIRST_TEST_ACCOUNT;
trade.bid = false;
trade.type = cryptonote::cc_command_trade_t::type_flag;
trade.id = 2 + PREDEFINED_BUILDINGS;
trade.amount = 1;
trade.price = 10 * COIN;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = 0;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 0;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
const uint64_t construction_height = 82 + mixin; // brittle
cryptonote::cc_command_demolish_t demolish;
demolish.cc_account = FIRST_TEST_ACCOUNT;
demolish.flag = 2 + PREDEFINED_BUILDINGS;
demolish.role = settings.role;
demolish.economic_power = settings.economic_power;
demolish.repair = DEFAULT_REPAIR;
demolish.construction_height = construction_height;
demolish.last_service_height = construction_height;
demolish.service_price = 0;
demolish.active = false;
demolish.ignore = false;
demolish.crop = CROP_NONE;
demolish.sow_height = 0;
demolish.num_missed_ticks = 0;
demolish.num_fishing_ticks = 0;
demolish.fishing_distance = 0;
demolish.fishing_city = 0;
demolish.fish = 0;
demolish.builder = FIRST_TEST_ACCOUNT;
std::map<uint32_t, uint32_t> budget;
cc::get_build_settings_requirements(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, settings.role, settings.economic_power, budget, 255);
budget[ITEM_VEGETATION] += cc::get_num_vegetation(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, settings.role, settings.economic_power);
budget[ITEM_LIGHTSOURCE] += cc::get_num_lightsources(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, settings.role, settings.economic_power);
budget[ITEM_WATER] += cc::get_num_water(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, settings.role, settings.economic_power);
for (const auto &e: budget)
if (e.second)
demolish.budget.push_back({e.first, e.second});
demolish.tiles = {};
cmds.push_back(std::make_tuple("", demolish, BARE_TX_FEE));
trade.cc_account = FIRST_TEST_ACCOUNT + 1;
trade.bid = true;
trade.type = cryptonote::cc_command_trade_t::type_flag;
trade.id = 2 + PREDEFINED_BUILDINGS;
trade.amount = 1;
trade.price = 10 * COIN;
trade.accrual_start_height = 0;
trade.accrual = 0;
trade.accrual_price_limit = 0;
trade.flag_construction_height = construction_height;
trade.expiration = (MIN_TRADE_EXPIRATION + MAX_TRADE_EXPIRATION) / 2;
trade.cost = 10 * COIN;
cmds.push_back(std::make_tuple("", trade, BARE_TX_FEE));
std::vector<cryptonote::cc_command_trade_t::match_t> matches;
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [&](transaction &tx) {
if (tx.cc_cmd.type() != typeid(cryptonote::cc_command_trade_t))
return;
if (matches.size() < 1)
{
matches.push_back({boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).cc_nonce, 1});
}
else
{
boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd).matches = matches;
const auto &sender_account_keys = cc_test_accounts[1].get_keys();
const crypto::hash h = cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN);
cc::generate_signature(h, sender_account_keys.m_account_address.m_spend_public_key, sender_account_keys.m_spend_secret_key, tx.cc_account_signature);
}
});
}
uint64_t gen_cc_tx_valid_cc_repair::money_cost = 0;
std::map<uint32_t, uint32_t> gen_cc_tx_valid_cc_repair::item_balances;
uint64_t gen_cc_tx_valid_cc_repair::land_tax = 0;
int64_t gen_cc_tx_valid_cc_repair::game_update_treasury_delta = 0;
uint32_t gen_cc_tx_valid_cc_repair::expected_repair = 0;
std::map<uint32_t, uint64_t> gen_cc_tx_valid_cc_repair::prestige_bonuses;
bool gen_cc_tx_valid_cc_repair::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint64_t land_cost;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
item_balances[ITEM_BASIC_STONE] = STARTING_BLOCK_1;
item_balances[ITEM_BASIC_WOOD] = STARTING_BLOCK_2;
item_balances[ITEM_LABOUR] = STARTING_LABOUR;
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 200;
buy_land.y = oy + 200;
buy_land.wm1 = 11;
buy_land.hm1 = 11;
if (!cc::get_new_flag_cost(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, land_cost))
return false;
money_cost += land_cost;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
std::map<uint32_t, uint32_t> budget;
if (!cc::get_build_settings_requirements(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, settings.role, settings.economic_power, budget, 255))
return false;
for (const auto &e: budget)
item_balances[e.first] -= e.second;
cryptonote::cc_command_repair_t repair;
repair.cc_account = FIRST_TEST_ACCOUNT;
repair.flags.push_back({1 + PREDEFINED_BUILDINGS, MIN_DECAY_RATE});
cmds.push_back(std::make_tuple("", repair, BARE_TX_FEE));
expected_repair = DEFAULT_REPAIR + MIN_DECAY_RATE; // technically overflows, but the +MIN_DECAY_RATE happens after the game update below
std::map<uint32_t, uint32_t> costs;
cc::get_repair_costs(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, settings.role, settings.economic_power, false, 1500, costs, 255);
for (const auto &e: costs)
item_balances[e.first] -= e.second;
land_tax = 0;
uint64_t tax;
if (!cc::get_land_tax(ox + PREP_BUY_LAND_X, oy + PREP_BUY_LAND_Y, ox + PREP_BUY_LAND_X + PREP_BUY_LAND_WM1, oy + PREP_BUY_LAND_Y + PREP_BUY_LAND_HM1, ox, oy, 100, 0, 0, {}, tax))
return false;
land_tax += tax;
if (!cc::get_land_tax(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, settings.economic_power, 0, 0, {}, tax))
return false;
land_tax += tax;
return generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, valid, true, NULL, NULL, NULL);
}
bool gen_cc_tx_valid_cc_repair::generate_game_update_command(cryptonote::core &c, size_t ev_index, const std::vector<test_event_entry> &events_)
{
bool ret = gen_cc_tx_validation_base::generate_game_update_command(c, ev_index, events_);
if (!ret) return false;
std::vector<test_event_entry> &events = const_cast<std::vector<test_event_entry>&>(events_);
if (ev_index + 1 >= events.size())
{
MERROR("event index is out of range");
return false;
}
auto &e = events[ev_index + 1];
if (e.type() != typeid(cryptonote::block))
{
MERROR("Game update event is not a block");
return false;
}
auto &b = boost::get<cryptonote::block>(e);
auto &cg = boost::get<cryptonote::cc_command_game_update_t>(b.miner_tx.cc_cmd);
auto &city = cg.cities.back();
uint32_t account = 0xffffffffu;
for (const auto &adj: city.balances)
{
account += adj.delta_account + 1;
if (account == FIRST_TEST_ACCOUNT - 1)
game_update_treasury_delta = adj.delta;
}
if (city.repair.size() != 1 || city.repair[0].delta_id != 1 + PREDEFINED_BUILDINGS)
return false;
expected_repair += city.repair[0].delta_repair;
for (const auto &e: game_events)
{
if (e.cmd == get_cc_tag<uint8_t>(cryptonote::cc_command_game_update_t()))
if (boost::ends_with(e.event, " prestige bonus"))
prestige_bonuses[e.account] += e.balance;
}
return true;
}
bool gen_cc_tx_valid_cc_repair::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
uint32_t repair = 0;
BlockchainDB &db = c.get_blockchain_storage().get_db();
if (!db.get_cc_flag_repair(1 + PREDEFINED_BUILDINGS, repair))
{
MERROR("Error in get_cc_flag_repair");
return false;
}
if (repair != expected_repair)
{
MERROR("Repair is not the expected value: expected " << expected_repair << ", got " << repair);
return false;
}
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] + prestige_bonuses[FIRST_TEST_ACCOUNT] - 3 * BARE_TX_FEE - money_cost - land_tax)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] + prestige_bonuses[FIRST_TEST_ACCOUNT + 1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2] + prestige_bonuses[FIRST_TEST_ACCOUNT + 2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3] + prestige_bonuses[FIRST_TEST_ACCOUNT + 3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4] + prestige_bonuses[FIRST_TEST_ACCOUNT + 4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5] + prestige_bonuses[FIRST_TEST_ACCOUNT + 5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6] + prestige_bonuses[FIRST_TEST_ACCOUNT + 6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7] + prestige_bonuses[FIRST_TEST_ACCOUNT + 7])
&& expect_treasury_balance(c, expected_treasury_balance + money_cost + game_update_treasury_delta)
&& expect_item_balances(c, FIRST_TEST_ACCOUNT, {std::make_pair(ITEM_BASIC_STONE, item_balances[ITEM_BASIC_STONE]), std::make_pair(ITEM_BASIC_WOOD, item_balances[ITEM_BASIC_WOOD]), std::make_pair(ITEM_LABOUR, item_balances[ITEM_LABOUR])});
}
bool gen_cc_tx_invalid_cc_repair_past_max::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 200;
buy_land.y = oy + 200;
buy_land.wm1 = 11;
buy_land.hm1 = 11;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_repair_t repair;
repair.cc_account = FIRST_TEST_ACCOUNT;
repair.flags.push_back({1 + PREDEFINED_BUILDINGS, 4501});
cmds.push_back(std::make_tuple("", repair, BARE_TX_FEE));
return generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, invalid, true, NULL, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_repair_negative::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 200;
buy_land.y = oy + 200;
buy_land.wm1 = 11;
buy_land.hm1 = 11;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_repair_t repair;
repair.cc_account = FIRST_TEST_ACCOUNT;
repair.flags.push_back({1 + PREDEFINED_BUILDINGS, (uint32_t)-1});
cmds.push_back(std::make_tuple("", repair, BARE_TX_FEE));
return generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, invalid, true, NULL, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_repair_invalid_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 200;
buy_land.y = oy + 200;
buy_land.wm1 = 11;
buy_land.hm1 = 11;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_repair_t repair;
repair.cc_account = FIRST_TEST_ACCOUNT;
repair.flags.push_back({10, 4500});
cmds.push_back(std::make_tuple("", repair, BARE_TX_FEE));
return generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, invalid, true, NULL, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_repair_unowned_flag::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 200;
buy_land.y = oy + 200;
buy_land.wm1 = 11;
buy_land.hm1 = 11;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 1 + PREDEFINED_BUILDINGS;
settings.role = ROLE_RESIDENTIAL1;
settings.economic_power = 100;
settings.construction_height = 79 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
cryptonote::cc_command_repair_t repair;
repair.cc_account = FIRST_TEST_ACCOUNT + 1;
repair.flags.push_back({1 + PREDEFINED_BUILDINGS, 4500});
cmds.push_back(std::make_tuple("", repair, BARE_TX_FEE));
return generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, invalid, true, NULL, NULL, NULL);
}
uint64_t gen_cc_tx_valid_huge_game_update::land_tax = 0;
int64_t gen_cc_tx_valid_huge_game_update::game_update_treasury_delta = 0;
std::map<uint32_t, uint64_t> gen_cc_tx_valid_huge_game_update::prestige_bonuses;
bool gen_cc_tx_valid_huge_game_update::generate(std::vector<test_event_entry>& events) const
{
cryptonote::cc_command_game_update_t::test_payload_template.resize(1024 * 1024, '\0');
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t buy_items;
buy_items.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1;
buy_items.entries.push_back(e);
cmds.push_back(std::make_tuple("", buy_items, BARE_TX_FEE));
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
if (!cc::get_land_tax(ox + PREP_BUY_LAND_X, oy + PREP_BUY_LAND_Y, ox + PREP_BUY_LAND_X + PREP_BUY_LAND_WM1, oy + PREP_BUY_LAND_Y + PREP_BUY_LAND_HM1, ox, oy, 100, 0, 0, {}, land_tax))
return false;
bool ret = generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, valid, true, NULL, NULL, NULL);
if (!ret)
{
cryptonote::cc_command_game_update_t::test_payload_template.clear();
return false;
}
return true;
}
bool gen_cc_tx_valid_huge_game_update::generate_game_update_command(cryptonote::core &c, size_t ev_index, const std::vector<test_event_entry> &events_)
{
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([]() {
cryptonote::cc_command_game_update_t::test_payload_template.clear();
});
bool ret = gen_cc_tx_validation_base::generate_game_update_command(c, ev_index, events_);
if (!ret) return false;
std::vector<test_event_entry> &events = const_cast<std::vector<test_event_entry>&>(events_);
if (ev_index + 1 >= events.size())
{
MERROR("event index is out of range");
return false;
}
auto &e = events[ev_index + 1];
if (e.type() != typeid(cryptonote::block))
{
MERROR("Game update event is not a block");
return false;
}
auto &b = boost::get<cryptonote::block>(e);
auto &cg = boost::get<cryptonote::cc_command_game_update_t>(b.miner_tx.cc_cmd);
const size_t game_update_tx_size = cryptonote::tx_to_blob(b.miner_tx).size();
MINFO("Game update tx: " << game_update_tx_size);
MINFO("Game update block: " << cryptonote::block_to_blob(b).size());
if (game_update_tx_size <= 1024 * 1024)
{
MERROR("Game update tx is not as large as we want");
return false;
}
auto &city = cg.cities.back();
uint32_t account = 0xffffffffu;
for (const auto &adj: city.balances)
{
account += adj.delta_account + 1;
if (account == FIRST_TEST_ACCOUNT - 1)
game_update_treasury_delta = adj.delta;
}
for (const auto &e: game_events)
{
if (e.cmd == get_cc_tag<uint8_t>(cryptonote::cc_command_game_update_t()))
if (boost::ends_with(e.event, " prestige bonus"))
prestige_bonuses[e.account] += e.balance;
}
return true;
}
bool gen_cc_tx_valid_huge_game_update::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] + prestige_bonuses[FIRST_TEST_ACCOUNT] - cc::get_last_resort_price(ITEM_BASIC_STONE) - BARE_TX_FEE - land_tax)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1] + prestige_bonuses[FIRST_TEST_ACCOUNT + 1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2] + prestige_bonuses[FIRST_TEST_ACCOUNT + 2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3] + prestige_bonuses[FIRST_TEST_ACCOUNT + 3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4] + prestige_bonuses[FIRST_TEST_ACCOUNT + 4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5] + prestige_bonuses[FIRST_TEST_ACCOUNT + 5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6] + prestige_bonuses[FIRST_TEST_ACCOUNT + 6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7] + prestige_bonuses[FIRST_TEST_ACCOUNT + 7])
&& expect_treasury_balance(c, expected_treasury_balance + cc::get_last_resort_price(ITEM_BASIC_STONE) + game_update_treasury_delta);
}
bool gen_cc_tx_valid_cc_bare_new_item::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_new_item_t new_item;
new_item.cc_account = FIRST_TEST_ACCOUNT;
new_item.amount = 35;
new_item.name = "Test item";
new_item.primary_description = "Primary description";
new_item.secondary_description = "Secondary description";
new_item.is_group = false;
new_item.is_public = false;
new_item.group = 0;
new_item.gold = 0;
new_item.can_create_more = 0;
new_item.prestige_bonus = 0;
new_item.consumable = 0;
cmds.push_back(std::make_tuple("", new_item, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, valid, NULL, NULL);
}
bool gen_cc_tx_valid_cc_bare_new_item::check_final_state(cryptonote::core &c, const std::vector<test_event_entry> &events)
{
return log_test_accounts(c, events)
&& expect_cc_account(c, 0, FIRST_TEST_ACCOUNT, expected_balance[0] - 1 * BARE_TX_FEE - NEW_ITEM_FEE)
&& expect_cc_account(c, 1, FIRST_TEST_ACCOUNT + 1, expected_balance[1])
&& expect_cc_account(c, 2, FIRST_TEST_ACCOUNT + 2, expected_balance[2])
&& expect_cc_account(c, 3, FIRST_TEST_ACCOUNT + 3, expected_balance[3])
&& expect_cc_account(c, 4, FIRST_TEST_ACCOUNT + 4, initial_funding[4])
&& expect_cc_account(c, 5, FIRST_TEST_ACCOUNT + 5, initial_funding[5])
&& expect_cc_account(c, 6, FIRST_TEST_ACCOUNT + 6, initial_funding[6])
&& expect_cc_account(c, 7, FIRST_TEST_ACCOUNT + 7, initial_funding[7])
&& expect_treasury_balance(c, expected_treasury_balance + NEW_ITEM_FEE);
}
bool gen_cc_tx_invalid_cc_bare_new_item_zero_amount::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_new_item_t new_item;
new_item.cc_account = FIRST_TEST_ACCOUNT;
new_item.amount = 0;
new_item.name = "Test item";
new_item.primary_description = "Primary description";
new_item.secondary_description = "Secondary description";
new_item.is_group = false;
new_item.is_public = false;
new_item.group = 0;
new_item.gold = 0;
new_item.can_create_more = false;
new_item.prestige_bonus = 0;
new_item.consumable = 0;
cmds.push_back(std::make_tuple("", new_item, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_new_item_no_name::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_new_item_t new_item;
new_item.cc_account = FIRST_TEST_ACCOUNT;
new_item.amount = 35;
new_item.name = "";
new_item.primary_description = "Primary description";
new_item.secondary_description = "Secondary description";
new_item.is_group = false;
new_item.is_public = false;
new_item.group = 0;
new_item.gold = 0;
cmds.push_back(std::make_tuple("", new_item, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_new_item_invalid_name::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_new_item_t new_item;
new_item.cc_account = FIRST_TEST_ACCOUNT;
new_item.amount = 35;
new_item.name = "ABC\002D";
new_item.primary_description = "Primary description";
new_item.secondary_description = "Secondary description";
new_item.is_group = false;
new_item.is_public = false;
new_item.group = 0;
new_item.gold = 0;
cmds.push_back(std::make_tuple("", new_item, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_new_item_duplicate_name::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_new_item_t new_item;
new_item.cc_account = FIRST_TEST_ACCOUNT;
new_item.amount = 35;
new_item.name = "Test item";
new_item.primary_description = "Primary description";
new_item.secondary_description = "Secondary description";
new_item.is_group = false;
new_item.is_public = false;
new_item.group = 0;
new_item.gold = 0;
new_item.can_create_more = 0;
new_item.prestige_bonus = 0;
new_item.consumable = 0;
cmds.push_back(std::make_tuple("", new_item, BARE_TX_FEE));
cmds.push_back(std::make_tuple("", new_item, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_ignore_wrong_account::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_ignore_t ignore;
ignore.cc_account = FIRST_TEST_ACCOUNT;
ignore.type = cryptonote::cc_command_ignore_t::type_account;
ignore.id.push_back(FIRST_TEST_ACCOUNT);
ignore.ignore = true;
cmds.push_back(std::make_tuple("", ignore, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_new_event_badge_wrong_account::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_event_badge_t event_badge;
event_badge.cc_account = FIRST_TEST_ACCOUNT;
event_badge.badge_id = 0;
event_badge.name = "test badge";
event_badge.description = "test badge desc";
event_badge.instances.push_back({FIRST_TEST_ACCOUNT, 1});
cmds.push_back(std::make_tuple("", event_badge, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
}
bool gen_cc_tx_invalid_cc_bare_reused_nonce::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), mixin, amount_paid, true, cmds, false, invalid_on_block, NULL, [](transaction &tx) {
cryptonote::cc_command_basenonce_t *basenonce = cryptonote::get_cc_command_basenonce(tx.cc_cmd);
if (!basenonce)
return false;
basenonce->cc_nonce = 4000;
tx.invalidate_hashes();
const crypto::public_key pkey = cc_test_accounts[0].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[0].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
return true;
});
}
bool gen_cc_tx_valid_cc_embedded_data_all_bytes::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<bool> embedded_data;
const char *text = "The quick brown fox jumps over the lazy dog";
for (const char *ptr = text; *ptr; ++ptr)
for (int i = 0; i < 8; ++i)
embedded_data.push_back(!!((*ptr >> i) & 1));
for (int c = 0; c < 256; ++c) // any byte, including NUL, works
for (int i = 0; i < 8; ++i)
embedded_data.push_back(!!((c >> i) & 1));
const size_t n_input_bits = embedded_data.size();
bool verified = false;
return generate_with_full(events, boost::none, boost::none, prep_none, 1, 1, mixin, amount_paid, false, {}, false, valid, false, NULL,
[&](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {
if (destinations.empty())
return false;
tx_destination_entry &td = destinations[0];
td.embedded_data = embedded_data;
return true;
},
[&](transaction &tx) {
hw::device &hwdev = hw::get_device("default");
for (size_t i = 0; i < tx.vout.size(); ++i)
{
const cryptonote::txout_to_tagged_key &ottk = boost::get<cryptonote::txout_to_tagged_key>(tx.vout[i].target);
const crypto::public_key output_public_key = ottk.key;
if (!is_out_to_acc(cc_test_accounts[0].get_keys(), output_public_key, get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), i))
continue;
crypto::key_derivation derivation;
const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx.extra);
generate_key_derivation(tx_pub_key, cc_test_accounts[0].get_keys().m_view_secret_key, derivation);
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, i, scalar1);
std::vector<bool> bits = rct::getRctEmbeddedData(tx.rct_signatures, rct::sk2rct(scalar1), i, hwdev);
if (bits.size() < n_input_bits)
{
MERROR("Got " << bits.size() << " bits, expected " << n_input_bits);
return false;
}
for (size_t k = 0; k < n_input_bits; ++k)
{
if (bits[k] != embedded_data[k])
{
MERROR("Bit " << k << " is wrong");
return false;
}
}
for (size_t k = n_input_bits; k < embedded_data.size(); ++k)
{
if (embedded_data[k])
{
MERROR("Bit " << k << " is set but after encoded data");
return false;
}
}
verified = true;
}
return true;
}
) && verified;
}
bool gen_cc_tx_valid_cc_embedded_data_capacity::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<bool> embedded_data;
const size_t capacity = mixin * 251;
embedded_data.resize(capacity, true);
const size_t n_input_bits = embedded_data.size();
bool verified = false;
return generate_with_full(events, boost::none, boost::none, prep_none, 1, 1, mixin, amount_paid, false, {}, false, valid, false, NULL,
[&](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {
if (destinations.empty())
return false;
tx_destination_entry &td = destinations[0];
td.embedded_data = embedded_data;
return true;
},
[&](transaction &tx) {
hw::device &hwdev = hw::get_device("default");
for (size_t i = 0; i < tx.vout.size(); ++i)
{
const cryptonote::txout_to_tagged_key &ottk = boost::get<cryptonote::txout_to_tagged_key>(tx.vout[i].target);
const crypto::public_key output_public_key = ottk.key;
if (!is_out_to_acc(cc_test_accounts[0].get_keys(), output_public_key, get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), i))
continue;
crypto::key_derivation derivation;
const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx.extra);
generate_key_derivation(tx_pub_key, cc_test_accounts[0].get_keys().m_view_secret_key, derivation);
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, i, scalar1);
std::vector<bool> bits = rct::getRctEmbeddedData(tx.rct_signatures, rct::sk2rct(scalar1), i, hwdev);
if (bits.size() < n_input_bits)
{
MERROR("Got " << bits.size() << " bits, expected " << n_input_bits);
return false;
}
for (size_t k = 0; k < n_input_bits; ++k)
{
if (bits[k] != embedded_data[k])
{
MERROR("Bit " << k << " is wrong");
return false;
}
}
for (size_t k = n_input_bits; k < embedded_data.size(); ++k)
{
if (embedded_data[k])
{
MERROR("Bit " << k << " is set but after encoded data");
return false;
}
}
verified = true;
}
return true;
}
) && verified;
}
bool gen_cc_tx_invalid_cc_embedded_data_too_long::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<bool> embedded_data;
const size_t capacity = mixin * 251;
embedded_data.resize(capacity + 1, true);
return generate_with_full(events, boost::none, boost::none, prep_none, 1, 1, mixin, amount_paid, false, {}, false, invalid_on_creation, false, NULL,
[&](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {
if (destinations.empty())
return false;
tx_destination_entry &td = destinations[0];
td.embedded_data = embedded_data;
return true;
},
NULL
);
}
bool gen_cc_tx_valid_cc_embedded_data_multiring::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<bool> embedded_data;
const size_t capacity = mixin * 251 * 4;
embedded_data.reserve(capacity);
for (size_t i = 0; i < capacity; ++i)
embedded_data.push_back(!!((i * 17) & 1));
const size_t n_input_bits = embedded_data.size();
bool verified = false;
return generate_with_full(events, boost::none, boost::none, prep_none, 1, 4, mixin, amount_paid, false, {}, false, valid, false, NULL,
[&](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {
if (destinations.empty())
return false;
tx_destination_entry &td = destinations[0];
td.embedded_data = embedded_data;
return true;
},
[&](transaction &tx) {
hw::device &hwdev = hw::get_device("default");
for (size_t i = 0; i < tx.vout.size(); ++i)
{
const cryptonote::txout_to_tagged_key &ottk = boost::get<cryptonote::txout_to_tagged_key>(tx.vout[i].target);
const crypto::public_key output_public_key = ottk.key;
if (!is_out_to_acc(cc_test_accounts[0].get_keys(), output_public_key, get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), i))
continue;
crypto::key_derivation derivation;
const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx.extra);
generate_key_derivation(tx_pub_key, cc_test_accounts[0].get_keys().m_view_secret_key, derivation);
crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, i, scalar1);
std::vector<bool> bits = rct::getRctEmbeddedData(tx.rct_signatures, rct::sk2rct(scalar1), i, hwdev);
if (bits.size() < n_input_bits)
{
MERROR("Got " << bits.size() << " bits, expected " << n_input_bits);
return false;
}
for (size_t k = 0; k < n_input_bits; ++k)
{
if (bits[k] != embedded_data[k])
{
MERROR("Bit " << k << " is wrong");
return false;
}
}
for (size_t k = n_input_bits; k < embedded_data.size(); ++k)
{
if (embedded_data[k])
{
MERROR("Bit " << k << " is set but after encoded data");
return false;
}
}
verified = true;
}
return true;
}
) && verified;
return false;
}
bool gen_cc_tx_invalid_cc_embedded_data_multiple_recipients::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<bool> embedded_data;
const size_t capacity = 64;
embedded_data.resize(capacity, true);
return generate_with_full(events, boost::none, boost::none, prep_none, 1, 1, mixin, amount_paid, false, {}, false, invalid_on_creation, false, NULL,
[&](std::vector<tx_source_entry> &sources, std::vector<tx_destination_entry> &destinations) {
if (destinations.size() < 2)
return false;
destinations[0].embedded_data = embedded_data;
destinations[1].embedded_data = embedded_data;
return true;
},
NULL
);
}
bool gen_cc_tx_invalid_cc_wrong_command_version_too_low::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [](transaction &tx) {
cryptonote::cc_command_basenonce_t *basenonce = cryptonote::get_cc_command_basenonce(tx.cc_cmd);
if (!basenonce)
return false;
--basenonce->cc_version;
tx.invalidate_hashes();
const crypto::public_key pkey = cc_test_accounts[0].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[0].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
return true;
});
}
bool gen_cc_tx_invalid_cc_wrong_command_version_too_high::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [](transaction &tx) {
cryptonote::cc_command_basenonce_t *basenonce = cryptonote::get_cc_command_basenonce(tx.cc_cmd);
if (!basenonce)
return false;
++basenonce->cc_version;
tx.invalidate_hashes();
const crypto::public_key pkey = cc_test_accounts[0].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[0].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
return true;
});
}
bool gen_cc_tx_invalid_cc_wrong_command_version_zero::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, [](transaction &tx) {
cryptonote::cc_command_basenonce_t *basenonce = cryptonote::get_cc_command_basenonce(tx.cc_cmd);
if (!basenonce)
return false;
basenonce->cc_version = 0;
tx.invalidate_hashes();
const crypto::public_key pkey = cc_test_accounts[0].get_keys().m_account_address.m_spend_public_key;
const crypto::secret_key skey = cc_test_accounts[0].get_keys().m_spend_secret_key;
cc::generate_signature(cryptonote::get_transaction_prefix_hash_with_tag(tx, cryptonote::FAKECHAIN), pkey, skey, tx.cc_account_signature);
return true;
});
}
bool gen_cc_tx_pos_blocks::generate(std::vector<test_event_entry>& events) const
{
init_cc_test_accounts();
const unsigned int mixin = DEFAULT_MIXIN;
const uint64_t amount_paid = 0;
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
cryptonote::cc_command_buy_land_t buy_land;
buy_land.cc_account = FIRST_TEST_ACCOUNT;
buy_land.city = 0;
buy_land.x = ox + 240;
buy_land.y = oy + 20;
buy_land.wm1 = 63;
buy_land.hm1 = 63;
uint64_t land_cost;
if (!cc::get_new_flag_cost(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, land_cost))
return false;
cmds.push_back(std::make_tuple("", buy_land, BARE_TX_FEE));
cryptonote::cc_command_buy_items_t cmd;
cmd.cc_account = FIRST_TEST_ACCOUNT;
cryptonote::cc_command_buy_items_t::entry_t e;
e.type = ITEM_BASIC_STONE;
e.amount = 1700;
cmd.entries.push_back(e);
e.type = ITEM_BASIC_WOOD;
e.amount = 3800 + 250;
cmd.entries.push_back(e);
e.type = ITEM_LABOUR;
e.amount = 31500 + HUNT_LABOUR_COST;
cmd.entries.push_back(e);
cmds.push_back(std::make_tuple("", cmd, BARE_TX_FEE));
cryptonote::cc_command_building_settings_t settings;
settings.cc_account = FIRST_TEST_ACCOUNT;
settings.flag = 2 + PREDEFINED_BUILDINGS;
settings.role = ROLE_AGRICULTURAL;
settings.economic_power = 100;
settings.construction_height = 80 + mixin; // brittle
settings.name_cutoff = 0;
cmds.push_back(std::make_tuple("", settings, BARE_TX_FEE));
const uint64_t construction_height = 82 + mixin; // brittle
cryptonote::cc_command_buy_items_t buy_items; // dummy
buy_items.cc_account = FIRST_TEST_ACCOUNT;
buy_items.entries.push_back({ITEM_LABOUR, 1});
cmds.push_back(std::make_tuple("", buy_items, BARE_TX_FEE));
if (!generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, valid, true, [&buy_land, &settings](test_generator &generator, std::vector<test_event_entry> &events){
// now we have an active flag we can use for PoS
const auto &e = events[events.size() - 2];
if (e.type() != typeid(cryptonote::block))
{
MERROR("Last event is not a block");
return false;
}
auto &b = boost::get<cryptonote::block>(e);
cryptonote::block pos_block;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(pos_block, b, cc_test_accounts[0],
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version | test_generator::bf_pos_flag,
BASE_TEST_FORK, BASE_TEST_FORK, b.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN,
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0, 0, BASE_TEST_FORK, 0, settings.flag),
false, "Failed to generate block");
const uint32_t city_level = 0;
const uint64_t owner_prestige = 2; // very brittle, just happens to be that when the game is run on the generated txes
const uint64_t blockchain_height = GAME_UPDATE_FREQUENCY + 2;
cryptonote::txin_gen &in = boost::get<cryptonote::txin_gen>(pos_block.miner_tx.vin[0]);
in.weight = cc::get_pos_stake_weight(0, buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ROLE_AGRICULTURAL, 100,
construction_height, {}, 0, city_level, owner_prestige, blockchain_height, BASE_TEST_FORK);
crypto::secret_key skey;
crypto::public_key pkey;
cc::cc_derive_keys(cc_test_accounts[0].get_keys().m_spend_secret_key, skey, pkey);
cryptonote::create_pos_signature(in, pos_block.prev_id, pos_block.timestamp, skey, in.signature);
// this is now a valid pos_block, we will generate a number of invalid ones first
auto make_invalid_pos_block = [&pos_block, &events](const std::function<void(cryptonote::block&)> &f) {
cryptonote::block bad_block = pos_block;
f(bad_block);
DO_CALLBACK(events, "mark_invalid_block");
events.push_back(bad_block);
};
#define MAKE_INVALID_POS_BLOCK(x) \
make_invalid_pos_block([](cryptonote::block &bad_block) { \
cryptonote::txin_gen &bad_in = boost::get<cryptonote::txin_gen>(bad_block.miner_tx.vin[0]); \
(void)bad_in; \
x; \
})
#define SIGN(signer) \
crypto::secret_key skey; \
crypto::public_key pkey; \
cc::cc_derive_keys(cc_test_accounts[signer].get_keys().m_spend_secret_key, skey, pkey); \
cryptonote::create_pos_signature(bad_in, bad_block.prev_id, bad_block.timestamp, skey, bad_in.signature);
MAKE_INVALID_POS_BLOCK(bad_in.height += 1; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.weight = 0; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.weight += 1; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.weight -= 1; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.flag = 0; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.flag -= 1; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.flag = 999; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_block.nonce = 1 + 1; SIGN(0));
MAKE_INVALID_POS_BLOCK(bad_in.signature.r.data[0] += 1);
MAKE_INVALID_POS_BLOCK(bad_in.signature.c.data[0] += 1);
MAKE_INVALID_POS_BLOCK(memset(&bad_in.signature, 0, sizeof(bad_in.signature)));
MAKE_INVALID_POS_BLOCK(bad_block.timestamp += 1);
MAKE_INVALID_POS_BLOCK(bad_block.timestamp -= 1);
MAKE_INVALID_POS_BLOCK(SIGN(1));
#undef SIGN
#undef MAKE_INVALID_POS_BLOCK
// push the correct one last
events.push_back(pos_block);
return true;
}, NULL, NULL))
return false;
return true;
}