Merge dev changes

This commit is contained in:
doy-lee 2018-10-10 17:51:16 +11:00
parent 44f2822230
commit e2c8660d22
17 changed files with 499 additions and 289 deletions

View File

@ -337,8 +337,10 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
}
if (m_nettype == FAKECHAIN)
{
for (size_t n = 0; test_options->hard_forks[n].first; ++n)
m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1);
for (auto n = 0u; n < test_options->hard_forks.size(); ++n) {
const auto& hf = test_options->hard_forks.at(n);
m_hardfork->add_fork(hf.first, hf.second, 0, n + 1);
}
}
else if (m_nettype == TESTNET)
{

View File

@ -584,7 +584,7 @@ namespace cryptonote
MERROR("Failed to parse block notify spec");
}
const std::pair<uint8_t, uint64_t> regtest_hard_forks[3] = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)};
const std::vector<std::pair<uint8_t, uint64_t>> regtest_hard_forks = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)};
const cryptonote::test_options regtest_test_options = {
regtest_hard_forks
};

View File

@ -57,7 +57,7 @@ DISABLE_VS_WARNINGS(4355)
namespace cryptonote
{
struct test_options {
const std::pair<uint8_t, uint64_t> *hard_forks;
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks;
};
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir;

View File

@ -185,6 +185,17 @@ namespace
return buf;
}
bool input_line_and_parse_yes_no_result(char const *prompt)
{
std::string prompt_yes_no = std::string(prompt) + " (Y/Yes/N/No): ";
std::string result = input_line(prompt_yes_no);
if (std::cin.eof())
return false;
return command_line::is_yes(result);
}
boost::optional<tools::password_container> password_prompter(const char *prompt, bool verify)
{
#ifdef HAVE_READLINE
@ -5236,6 +5247,7 @@ bool simple_wallet::register_service_node_main(
de.amount = amount_payable_by_operator;
dsts.push_back(de);
bool submitted_to_network = false;
try
{
// figure out what tx will be necessary
@ -5339,6 +5351,7 @@ bool simple_wallet::register_service_node_main(
else
{
commit_or_save(ptx_vector, m_do_not_relay);
submitted_to_network = true;
}
}
catch (const tools::error::not_enough_unlocked_money& e)
@ -5364,10 +5377,27 @@ bool simple_wallet::register_service_node_main(
LOG_ERROR("unknown error");
fail_msg_writer() << tr("unknown error");
}
if (submitted_to_network && !autostake)
{
success_msg_writer() << tr("Wait for transaction to be included in a block before registration is complete.\n")
<< tr("Use the print_sn command in the daemon to check the status.");
}
return true;
}
static const char ASK_PASSWORD_MUST_BE_OFF_MSG[] = "Cannot autostake with ask-password set to true, passwords are scrubbed from memory after use. You must enter \"set ask-password 0\" to allow autostaking to work and disable scrubbing.";
static bool prompt_autostaking_non_trusted_contributors_warning()
{
success_msg_writer(false/*color*/)
<< tr("Auto staking to a reserved service node with non-trusted contributors may lock up your loki for the staking duration "
"if they do not restake after service node expiration.")
<< tr("\n\nIf this behaviour is not desirable, please reuse the staking command without the auto command");
bool result = input_line_and_parse_yes_no_result("Accept auto staking towards a reserved service node");
return result;
}
bool simple_wallet::register_service_node(const std::vector<std::string> &args_)
{
if (!try_connect_to_daemon())
@ -5461,7 +5491,6 @@ bool simple_wallet::register_service_node(const std::vector<std::string> &args_)
}
cryptonote::account_public_address address = addresses[0];
if (!m_wallet->contains_address(address))
{
fail_msg_writer() << tr("The first reserved address for this registration does not belong to this wallet.");
@ -5477,7 +5506,15 @@ bool simple_wallet::register_service_node(const std::vector<std::string> &args_)
if (autostake)
{
m_cmd_binder.stop_handling();
bool is_open_service_node = portions_for_operator != STAKING_PORTIONS;
if (is_open_service_node || portions.size() > 1)
{
if (!prompt_autostaking_non_trusted_contributors_warning())
return true;
}
stop();
m_idle_thread.join();
success_msg_writer(false) << please_wait_to_be_included_in_block_msg;
#ifndef WIN32
success_msg_writer(true /*color*/) << tr("Successfully entered autostaking mode, this wallet is moving into the background to automatically renew your service node every period.");
@ -5510,7 +5547,7 @@ bool simple_wallet::register_service_node(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::stake_main(
const crypto::public_key& service_node_key,
const cryptonote::account_public_address& address,
const cryptonote::address_parse_info& parse_info,
uint32_t priority,
std::set<uint32_t>& subaddr_indices,
uint64_t amount,
@ -5523,6 +5560,13 @@ bool simple_wallet::stake_main(
return true;
}
// sanity check address is not subaddress incase this gets called somewhere else that assumes it can be
if (parse_info.is_subaddress)
{
fail_msg_writer() << tr("Cannot stake from a subaddress");
return false;
}
m_wallet->refresh(false);
uint64_t staking_requirement_lock_blocks = service_nodes::get_staking_requirement_lock_blocks(m_wallet->nettype());
uint64_t locked_blocks = staking_requirement_lock_blocks + STAKING_REQUIREMENT_LOCK_BLOCKS_EXCESS;
@ -5578,23 +5622,19 @@ bool simple_wallet::stake_main(
}
const auto& snode_info = response.service_node_states.front();
bool full = false;
const uint64_t DUST = MAX_NUMBER_OF_CONTRIBUTORS;
if (amount == 0)
amount = snode_info.staking_requirement * amount_fraction;
const bool full = snode_info.contributors.size() >= MAX_NUMBER_OF_CONTRIBUTORS;
uint64_t can_contrib_total = 0;
uint64_t must_contrib_total = 0;
if (snode_info.contributors.size() < MAX_NUMBER_OF_CONTRIBUTORS)
if (!full)
{
can_contrib_total = snode_info.staking_requirement - snode_info.total_reserved;
must_contrib_total = service_nodes::get_min_node_contribution(snode_info.staking_requirement, snode_info.total_reserved);
}
else
full = true;
bool is_preexisting_contributor = false;
for (const auto& contributor : snode_info.contributors)
@ -5603,7 +5643,7 @@ bool simple_wallet::stake_main(
if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), contributor.address))
info.address = service_nodes::null_address;
if (info.address == address)
if (info.address == parse_info.address)
{
uint64_t max_increase_reserve = snode_info.staking_requirement - snode_info.total_reserved;
uint64_t max_increase_amount_to = contributor.reserved + max_increase_reserve;
@ -5618,6 +5658,7 @@ bool simple_wallet::stake_main(
fail_msg_writer() << tr("This service node already has the maximum number of participants, and the specified address is not one of them");
return true;
}
if (can_contrib_total == 0)
{
if (!autostake)
@ -5667,11 +5708,11 @@ bool simple_wallet::stake_main(
add_service_node_pubkey_to_tx_extra(extra, service_node_key);
add_service_node_contributor_to_tx_extra(extra, address);
add_service_node_contributor_to_tx_extra(extra, parse_info.address);
vector<cryptonote::tx_destination_entry> dsts;
cryptonote::tx_destination_entry de;
de.addr = address;
de.addr = parse_info.address;
de.is_subaddress = false;
de.amount = amount;
dsts.push_back(de);
@ -5883,6 +5924,7 @@ bool simple_wallet::stake(const std::vector<std::string> &args_)
}
}
std::string const &address_str = local_args[1];
cryptonote::address_parse_info info;
if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[1], oa_prompter))
{
@ -5912,8 +5954,55 @@ bool simple_wallet::stake(const std::vector<std::string> &args_)
if (autostake)
{
m_cmd_binder.stop_handling();
{
const auto& response = m_wallet->get_service_nodes({ epee::string_tools::pod_to_hex(service_node_key) });
if (response.service_node_states.size() != 1)
{
fail_msg_writer() << tr("Could not find service node in service node list, please make sure it is registered first.");
return false;
}
const auto& snode_info = response.service_node_states.front();
bool preexisting_contributor = false;
for (const auto& contributor : snode_info.contributors)
{
preexisting_contributor = (contributor.address == address_str);
if (preexisting_contributor) break;
}
if (!preexisting_contributor)
{
// NOTE: Disallowed since there isn't a sensible way to recalculate the portions of the staker reliably
fail_msg_writer() << tr("Autostaking is disallowed for contributors who did not reserve a spot in a service node");
return false;
}
// Autostaking in reserved pools warning
if (snode_info.contributors.size() > 1 && !prompt_autostaking_non_trusted_contributors_warning())
{
return true;
}
}
if (amount_fraction == 0) // Fixed amount loki warning
{
success_msg_writer(false/*color*/) << tr("You're autostaking to a service node using a fixed amount of loki: ")
<< print_money(amount)
<< tr(".\nThe staking requirement will be different after the service node expires. Staking a fixed amount "
"may change your percentage of stake towards the service node and consequently your block reward allocation.")
<< tr("\n\nIf this behaviour is not desirable, please reuse the staking command with a percentage sign.");
if (!input_line_and_parse_yes_no_result("Accept staking with a fixed amount of loki"))
{
fail_msg_writer() << tr("Staking transaction with fixed loki specified cancelled.");
return true;
}
success_msg_writer(false/*color*/) << "\n";
}
stop();
m_idle_thread.join();
#ifndef WIN32
success_msg_writer() << tr("Entering autostaking mode, forking to background...");
tools::threadpool::getInstance().stop();
@ -5927,7 +6016,7 @@ bool simple_wallet::stake(const std::vector<std::string> &args_)
{
if (!m_idle_run.load(std::memory_order_relaxed))
break;
if (!stake_main(service_node_key, info.address, priority, subaddr_indices, amount, amount_fraction, autostake))
if (!stake_main(service_node_key, info, priority, subaddr_indices, amount, amount_fraction, autostake))
break;
if (!m_idle_run.load(std::memory_order_relaxed))
break;
@ -5936,7 +6025,7 @@ bool simple_wallet::stake(const std::vector<std::string> &args_)
}
else
{
stake_main(service_node_key, info.address, priority, subaddr_indices, amount, amount_fraction, autostake);
stake_main(service_node_key, info, priority, subaddr_indices, amount, amount_fraction, autostake);
}
return true;

View File

@ -232,7 +232,7 @@ namespace cryptonote
bool version(const std::vector<std::string>& args);
bool register_service_node_main(const std::vector<std::string>& service_node_key_as_str, uint64_t expiration_timestamp, const cryptonote::account_public_address& address, uint32_t priority, const std::vector<uint64_t>& portions, const std::vector<uint8_t>& extra, std::set<uint32_t>& subaddr_indices, bool autostake);
bool stake_main(const crypto::public_key& service_node_key, const cryptonote::account_public_address& address, uint32_t priority, std::set<uint32_t>& subaddr_indices, uint64_t amount, double amount_fraction, bool autostake);
bool stake_main(const crypto::public_key& service_node_key, const cryptonote::address_parse_info& parse_info, uint32_t priority, std::set<uint32_t>& subaddr_indices, uint64_t amount, double amount_fraction, bool autostake);
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr);

View File

@ -1,5 +1,5 @@
#define DEF_LOKI_VERSION_TAG "@VERSIONTAG@"
#define DEF_LOKI_VERSION "1.0.3"
#define DEF_LOKI_VERSION "1.0.4"
#define DEF_LOKI_RELEASE_NAME "Magic Mani"
#define DEF_LOKI_VERSION_FULL DEF_LOKI_VERSION "-" DEF_LOKI_VERSION_TAG

View File

@ -99,7 +99,7 @@ private:
template<>
struct get_test_options<gen_bp_tx_validation_base> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = {
std::make_pair(7, 0),
std::make_pair(8, 1),
std::make_pair(10, gen_bp_tx_validation_base::NUM_UNLOCKED_BLOCKS + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW + 1),

View File

@ -530,11 +530,10 @@ inline bool replay_events_through_core(cryptonote::core& cr, const std::vector<t
//--------------------------------------------------------------------------
template<typename t_test_class>
struct get_test_options {
const std::pair<uint8_t, uint64_t> hard_forks[2];
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = {{7, 0}};
const cryptonote::test_options test_options = {
hard_forks
};
get_test_options():hard_forks{std::make_pair((uint8_t)7, (uint64_t)0), std::make_pair((uint8_t)0, (uint64_t)0)}{}
};
//--------------------------------------------------------------------------

View File

@ -42,6 +42,7 @@ namespace
const command_line::arg_descriptor<bool> arg_generate_test_data = {"generate_test_data", ""};
const command_line::arg_descriptor<bool> arg_play_test_data = {"play_test_data", ""};
const command_line::arg_descriptor<bool> arg_generate_and_play_test_data = {"generate_and_play_test_data", ""};
const command_line::arg_descriptor<bool> arg_service_nodes = {"service_nodes", ""};
const command_line::arg_descriptor<bool> arg_test_transactions = {"test_transactions", ""};
const command_line::arg_descriptor<std::string> arg_filter = { "filter", "Regular expression filter for which tests to run" };
}
@ -62,6 +63,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_options, arg_generate_test_data);
command_line::add_arg(desc_options, arg_play_test_data);
command_line::add_arg(desc_options, arg_generate_and_play_test_data);
command_line::add_arg(desc_options, arg_service_nodes);
command_line::add_arg(desc_options, arg_test_transactions);
command_line::add_arg(desc_options, arg_filter);
@ -95,173 +97,191 @@ int main(int argc, char* argv[])
{
PLAY("chain001.dat", gen_simple_chain_001);
}
else if (command_line::get_arg(vm, arg_generate_and_play_test_data))
else if (command_line::get_arg(vm, arg_test_transactions))
{
// NOTE: Working tests
GENERATE_AND_PLAY(gen_service_nodes);
GENERATE_AND_PLAY(test_prefer_deregisters);
GENERATE_AND_PLAY(test_zero_fee_deregister);
GENERATE_AND_PLAY(test_deregister_safety_buffer);
CALL_TEST("TRANSACTIONS TESTS", test_transactions);
}
else
{
const bool run_all = !command_line::get_arg(vm, arg_service_nodes);
GENERATE_AND_PLAY(one_block);
if (run_all) {
MLOG(el::Level::Info, "Running all tests\n");
}
// Block verification tests
GENERATE_AND_PLAY(gen_block_big_major_version);
GENERATE_AND_PLAY(gen_block_big_minor_version);
GENERATE_AND_PLAY(gen_block_ts_not_checked);
GENERATE_AND_PLAY(gen_block_ts_in_past);
GENERATE_AND_PLAY(gen_block_ts_in_future);
GENERATE_AND_PLAY(gen_block_invalid_prev_id);
GENERATE_AND_PLAY(gen_block_invalid_nonce);
GENERATE_AND_PLAY(gen_block_no_miner_tx);
GENERATE_AND_PLAY(gen_block_unlock_time_is_low);
GENERATE_AND_PLAY(gen_block_unlock_time_is_high);
GENERATE_AND_PLAY(gen_block_unlock_time_is_timestamp_in_past);
GENERATE_AND_PLAY(gen_block_unlock_time_is_timestamp_in_future);
GENERATE_AND_PLAY(gen_block_height_is_low);
GENERATE_AND_PLAY(gen_block_height_is_high);
GENERATE_AND_PLAY(gen_block_miner_tx_has_2_tx_gen_in);
GENERATE_AND_PLAY(gen_block_miner_tx_with_txin_to_key);
GENERATE_AND_PLAY(gen_block_miner_tx_out_is_big);
GENERATE_AND_PLAY(gen_block_miner_tx_has_no_out);
GENERATE_AND_PLAY(gen_block_miner_tx_has_out_to_alice);
GENERATE_AND_PLAY(gen_block_has_invalid_tx);
GENERATE_AND_PLAY(gen_block_is_too_big);
if (run_all || command_line::get_arg(vm, arg_service_nodes))
{
GENERATE_AND_PLAY(gen_service_nodes);
GENERATE_AND_PLAY(test_prefer_deregisters);
GENERATE_AND_PLAY(test_zero_fee_deregister);
GENERATE_AND_PLAY(test_deregister_safety_buffer);
GENERATE_AND_PLAY(test_deregisters_on_split);
}
// Transaction verification tests
GENERATE_AND_PLAY(gen_tx_no_inputs_no_outputs);
if (run_all)
{
GENERATE_AND_PLAY(one_block);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_23_1__no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_45_5_23_no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_22_1__no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1__no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1_2_no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1_3_no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_2);
GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_2_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2);
GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_23_no_threshold);
// Block verification tests
GENERATE_AND_PLAY(gen_block_big_major_version);
GENERATE_AND_PLAY(gen_block_big_minor_version);
GENERATE_AND_PLAY(gen_block_ts_not_checked);
GENERATE_AND_PLAY(gen_block_ts_in_past);
GENERATE_AND_PLAY(gen_block_ts_in_future);
GENERATE_AND_PLAY(gen_block_invalid_prev_id);
GENERATE_AND_PLAY(gen_block_invalid_nonce);
GENERATE_AND_PLAY(gen_block_no_miner_tx);
GENERATE_AND_PLAY(gen_block_unlock_time_is_low);
GENERATE_AND_PLAY(gen_block_unlock_time_is_high);
GENERATE_AND_PLAY(gen_block_unlock_time_is_timestamp_in_past);
GENERATE_AND_PLAY(gen_block_unlock_time_is_timestamp_in_future);
GENERATE_AND_PLAY(gen_block_height_is_low);
GENERATE_AND_PLAY(gen_block_height_is_high);
GENERATE_AND_PLAY(gen_block_miner_tx_has_2_tx_gen_in);
GENERATE_AND_PLAY(gen_block_miner_tx_with_txin_to_key);
GENERATE_AND_PLAY(gen_block_miner_tx_out_is_big);
GENERATE_AND_PLAY(gen_block_miner_tx_has_no_out);
GENERATE_AND_PLAY(gen_block_miner_tx_has_out_to_alice);
GENERATE_AND_PLAY(gen_block_has_invalid_tx);
GENERATE_AND_PLAY(gen_block_is_too_big);
// Bulletproof Tests
GENERATE_AND_PLAY(gen_bp_tx_valid_1);
GENERATE_AND_PLAY(gen_bp_tx_invalid_1_1);
GENERATE_AND_PLAY(gen_bp_tx_valid_2);
GENERATE_AND_PLAY(gen_bp_tx_valid_3);
GENERATE_AND_PLAY(gen_bp_tx_valid_16);
GENERATE_AND_PLAY(gen_bp_tx_invalid_4_2_1);
GENERATE_AND_PLAY(gen_bp_tx_invalid_16_16);
GENERATE_AND_PLAY(gen_bp_txs_valid_2_and_2);
GENERATE_AND_PLAY(gen_bp_txs_invalid_2_and_8_2_and_16_16_1);
GENERATE_AND_PLAY(gen_bp_txs_valid_2_and_3_and_2_and_4);
GENERATE_AND_PLAY(gen_bp_tx_invalid_not_enough_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_empty_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_too_many_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_wrong_amount);
GENERATE_AND_PLAY(gen_bp_tx_invalid_borromean_type);
// Transaction verification tests
GENERATE_AND_PLAY(gen_tx_no_inputs_no_outputs);
// TODO(loki): Tests we need to fix
//GENERATE_AND_PLAY(gen_simple_chain_001);
//GENERATE_AND_PLAY(gen_simple_chain_split_1);
//GENERATE_AND_PLAY(gen_chain_switch_1);
//GENERATE_AND_PLAY(gen_ring_signature_1);
//GENERATE_AND_PLAY(gen_ring_signature_2);
////GENERATE_AND_PLAY(gen_ring_signature_big); // Takes up to XXX hours (if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10)
GENERATE_AND_PLAY(gen_multisig_tx_invalid_23_1__no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_45_5_23_no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_22_1__no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1__no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1_2_no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1_3_no_threshold);
GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_no_signers);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_23_no_threshold);
// Block verification tests
//GENERATE_AND_PLAY(gen_block_miner_tx_has_2_in);
////GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10
// Bulletproof Tests
GENERATE_AND_PLAY(gen_bp_tx_valid_1);
GENERATE_AND_PLAY(gen_bp_tx_invalid_1_1);
GENERATE_AND_PLAY(gen_bp_tx_valid_2);
GENERATE_AND_PLAY(gen_bp_tx_valid_3);
GENERATE_AND_PLAY(gen_bp_tx_valid_16);
GENERATE_AND_PLAY(gen_bp_tx_invalid_4_2_1);
GENERATE_AND_PLAY(gen_bp_tx_invalid_16_16);
GENERATE_AND_PLAY(gen_bp_txs_valid_2_and_2);
GENERATE_AND_PLAY(gen_bp_txs_invalid_2_and_8_2_and_16_16_1);
GENERATE_AND_PLAY(gen_bp_txs_valid_2_and_3_and_2_and_4);
GENERATE_AND_PLAY(gen_bp_tx_invalid_not_enough_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_empty_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_too_many_proofs);
GENERATE_AND_PLAY(gen_bp_tx_invalid_wrong_amount);
GENERATE_AND_PLAY(gen_bp_tx_invalid_borromean_type);
//// Transaction verification tests
// GENERATE_AND_PLAY(gen_tx_big_version);
// GENERATE_AND_PLAY(gen_tx_unlock_time);
// GENERATE_AND_PLAY(gen_tx_input_is_not_txin_to_key);
// GENERATE_AND_PLAY(gen_tx_no_inputs_has_outputs);
// GENERATE_AND_PLAY(gen_tx_has_inputs_no_outputs);
// GENERATE_AND_PLAY(gen_tx_invalid_input_amount);
// GENERATE_AND_PLAY(gen_tx_input_wo_key_offsets);
// GENERATE_AND_PLAY(gen_tx_sender_key_offest_not_exist);
// GENERATE_AND_PLAY(gen_tx_key_offest_points_to_foreign_key);
// GENERATE_AND_PLAY(gen_tx_mixed_key_offest_not_exist);
// GENERATE_AND_PLAY(gen_tx_key_image_not_derive_from_tx_key);
// GENERATE_AND_PLAY(gen_tx_key_image_is_invalid);
// GENERATE_AND_PLAY(gen_tx_check_input_unlock_time);
// GENERATE_AND_PLAY(gen_tx_txout_to_key_has_invalid_key);
// GENERATE_AND_PLAY(gen_tx_output_with_zero_amount);
// GENERATE_AND_PLAY(gen_tx_output_is_not_txout_to_key);
// GENERATE_AND_PLAY(gen_tx_signatures_are_invalid);
// TODO(loki): Tests we need to fix
#if 0
GENERATE_AND_PLAY(gen_simple_chain_001);
GENERATE_AND_PLAY(gen_simple_chain_split_1);
GENERATE_AND_PLAY(gen_chain_switch_1);
GENERATE_AND_PLAY(gen_ring_signature_1);
GENERATE_AND_PLAY(gen_ring_signature_2);
//GENERATE_AND_PLAY(gen_ring_signature_big); // Takes up to XXX hours (if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10)
//// Double spend
//GENERATE_AND_PLAY(gen_double_spend_in_tx<false>);
//GENERATE_AND_PLAY(gen_double_spend_in_tx<true>);
//GENERATE_AND_PLAY(gen_double_spend_in_the_same_block<false>);
//GENERATE_AND_PLAY(gen_double_spend_in_the_same_block<true>);
//GENERATE_AND_PLAY(gen_double_spend_in_different_blocks<false>);
//GENERATE_AND_PLAY(gen_double_spend_in_different_blocks<true>);
//GENERATE_AND_PLAY(gen_double_spend_in_different_chains);
//GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_the_same_block<false>);
//GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_the_same_block<true>);
//GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_different_blocks<false>);
//GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_different_blocks<true>);
Block verification tests
GENERATE_AND_PLAY(gen_block_miner_tx_has_2_in);
//GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10
//GENERATE_AND_PLAY(gen_uint_overflow_1);
//GENERATE_AND_PLAY(gen_uint_overflow_2);
// Transaction verification tests
GENERATE_AND_PLAY(gen_tx_big_version);
GENERATE_AND_PLAY(gen_tx_unlock_time);
GENERATE_AND_PLAY(gen_tx_input_is_not_txin_to_key);
GENERATE_AND_PLAY(gen_tx_no_inputs_has_outputs);
GENERATE_AND_PLAY(gen_tx_has_inputs_no_outputs);
GENERATE_AND_PLAY(gen_tx_invalid_input_amount);
GENERATE_AND_PLAY(gen_tx_input_wo_key_offsets);
GENERATE_AND_PLAY(gen_tx_sender_key_offest_not_exist);
GENERATE_AND_PLAY(gen_tx_key_offest_points_to_foreign_key);
GENERATE_AND_PLAY(gen_tx_mixed_key_offest_not_exist);
GENERATE_AND_PLAY(gen_tx_key_image_not_derive_from_tx_key);
GENERATE_AND_PLAY(gen_tx_key_image_is_invalid);
GENERATE_AND_PLAY(gen_tx_check_input_unlock_time);
GENERATE_AND_PLAY(gen_tx_txout_to_key_has_invalid_key);
GENERATE_AND_PLAY(gen_tx_output_with_zero_amount);
GENERATE_AND_PLAY(gen_tx_output_is_not_txout_to_key);
GENERATE_AND_PLAY(gen_tx_signatures_are_invalid);
//GENERATE_AND_PLAY(gen_block_reward);
// Double spend
GENERATE_AND_PLAY(gen_double_spend_in_tx<false>);
GENERATE_AND_PLAY(gen_double_spend_in_tx<true>);
GENERATE_AND_PLAY(gen_double_spend_in_the_same_block<false>);
GENERATE_AND_PLAY(gen_double_spend_in_the_same_block<true>);
GENERATE_AND_PLAY(gen_double_spend_in_different_blocks<false>);
GENERATE_AND_PLAY(gen_double_spend_in_different_blocks<true>);
GENERATE_AND_PLAY(gen_double_spend_in_different_chains);
GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_the_same_block<false>);
GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_the_same_block<true>);
GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_different_blocks<false>);
GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_different_blocks<true>);
//GENERATE_AND_PLAY(gen_v2_tx_mixable_0_mixin);
//GENERATE_AND_PLAY(gen_v2_tx_mixable_low_mixin);
// // GENERATE_AND_PLAY(gen_v2_tx_unmixable_only);
// // GENERATE_AND_PLAY(gen_v2_tx_unmixable_one);
// // GENERATE_AND_PLAY(gen_v2_tx_unmixable_two);
//GENERATE_AND_PLAY(gen_v2_tx_dust);
GENERATE_AND_PLAY(gen_uint_overflow_1);
GENERATE_AND_PLAY(gen_uint_overflow_2);
//GENERATE_AND_PLAY(gen_rct_tx_valid_from_pre_rct);
//GENERATE_AND_PLAY(gen_rct_tx_valid_from_rct);
//GENERATE_AND_PLAY(gen_rct_tx_valid_from_mixed);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_real_dest);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_real_mask);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_fake_dest);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_fake_mask);
//GENERATE_AND_PLAY(gen_rct_tx_rct_bad_real_dest);
//GENERATE_AND_PLAY(gen_rct_tx_rct_bad_real_mask);
//GENERATE_AND_PLAY(gen_rct_tx_rct_bad_fake_dest);
//GENERATE_AND_PLAY(gen_rct_tx_rct_bad_fake_mask);
//GENERATE_AND_PLAY(gen_rct_tx_rct_spend_with_zero_commit);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_zero_vin_amount);
//GENERATE_AND_PLAY(gen_rct_tx_rct_non_zero_vin_amount);
//GENERATE_AND_PLAY(gen_rct_tx_non_zero_vout_amount);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_duplicate_key_image);
//GENERATE_AND_PLAY(gen_rct_tx_rct_duplicate_key_image);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_wrong_key_image);
//GENERATE_AND_PLAY(gen_rct_tx_rct_wrong_key_image);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_wrong_fee);
//GENERATE_AND_PLAY(gen_rct_tx_rct_wrong_fee);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_remove_vin);
//GENERATE_AND_PLAY(gen_rct_tx_rct_remove_vin);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_add_vout);
//GENERATE_AND_PLAY(gen_rct_tx_rct_add_vout);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_increase_vin_and_fee);
//GENERATE_AND_PLAY(gen_rct_tx_pre_rct_altered_extra);
//GENERATE_AND_PLAY(gen_rct_tx_rct_altered_extra);
GENERATE_AND_PLAY(gen_block_reward);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_22_1_2);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_22_1_2_many_inputs);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_22_2_1);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_33_1_23);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_33_3_21);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_23_1_2);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_23_1_3);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_23_2_1);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_23_2_3);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_45_1_234);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_45_4_135_many_inputs);
//GENERATE_AND_PLAY(gen_multisig_tx_valid_89_3_1245789);
GENERATE_AND_PLAY(gen_v2_tx_mixable_0_mixin);
GENERATE_AND_PLAY(gen_v2_tx_mixable_low_mixin);
// GENERATE_AND_PLAY(gen_v2_tx_unmixable_only);
// GENERATE_AND_PLAY(gen_v2_tx_unmixable_one);
// GENERATE_AND_PLAY(gen_v2_tx_unmixable_two);
GENERATE_AND_PLAY(gen_v2_tx_dust);
GENERATE_AND_PLAY(gen_rct_tx_valid_from_pre_rct);
GENERATE_AND_PLAY(gen_rct_tx_valid_from_rct);
GENERATE_AND_PLAY(gen_rct_tx_valid_from_mixed);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_real_dest);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_real_mask);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_fake_dest);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_bad_fake_mask);
GENERATE_AND_PLAY(gen_rct_tx_rct_bad_real_dest);
GENERATE_AND_PLAY(gen_rct_tx_rct_bad_real_mask);
GENERATE_AND_PLAY(gen_rct_tx_rct_bad_fake_dest);
GENERATE_AND_PLAY(gen_rct_tx_rct_bad_fake_mask);
GENERATE_AND_PLAY(gen_rct_tx_rct_spend_with_zero_commit);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_zero_vin_amount);
GENERATE_AND_PLAY(gen_rct_tx_rct_non_zero_vin_amount);
GENERATE_AND_PLAY(gen_rct_tx_non_zero_vout_amount);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_duplicate_key_image);
GENERATE_AND_PLAY(gen_rct_tx_rct_duplicate_key_image);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_wrong_key_image);
GENERATE_AND_PLAY(gen_rct_tx_rct_wrong_key_image);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_wrong_fee);
GENERATE_AND_PLAY(gen_rct_tx_rct_wrong_fee);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_remove_vin);
GENERATE_AND_PLAY(gen_rct_tx_rct_remove_vin);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_add_vout);
GENERATE_AND_PLAY(gen_rct_tx_rct_add_vout);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_increase_vin_and_fee);
GENERATE_AND_PLAY(gen_rct_tx_pre_rct_altered_extra);
GENERATE_AND_PLAY(gen_rct_tx_rct_altered_extra);
GENERATE_AND_PLAY(gen_multisig_tx_valid_22_1_2);
GENERATE_AND_PLAY(gen_multisig_tx_valid_22_1_2_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_22_2_1);
GENERATE_AND_PLAY(gen_multisig_tx_valid_33_1_23);
GENERATE_AND_PLAY(gen_multisig_tx_valid_33_3_21);
GENERATE_AND_PLAY(gen_multisig_tx_valid_23_1_2);
GENERATE_AND_PLAY(gen_multisig_tx_valid_23_1_3);
GENERATE_AND_PLAY(gen_multisig_tx_valid_23_2_1);
GENERATE_AND_PLAY(gen_multisig_tx_valid_23_2_3);
GENERATE_AND_PLAY(gen_multisig_tx_valid_45_1_234);
GENERATE_AND_PLAY(gen_multisig_tx_valid_45_4_135_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_89_3_1245789);
GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_2);
GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_2_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2);
GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2_many_inputs);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234);
GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234_many_inputs);
#endif
}
el::Level level = (failed_tests.empty() ? el::Level::Info : el::Level::Error);
MLOG(level, "\nREPORT:");
@ -276,15 +296,6 @@ int main(int argc, char* argv[])
}
}
}
else if (command_line::get_arg(vm, arg_test_transactions))
{
CALL_TEST("TRANSACTIONS TESTS", test_transactions);
}
else
{
MERROR("Wrong arguments");
return 2;
}
return failed_tests.empty() ? 0 : 1;

View File

@ -73,11 +73,10 @@ bool gen_double_spend_in_different_chains::check_double_spend(cryptonote::core&
{
DEFINE_TESTS_ERROR_CONTEXT("gen_double_spend_in_different_chains::check_double_spend");
std::vector<block> block_list;
bool r = c.get_blocks(0, 100 + 2 * CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, block_list);
std::vector<block> blocks;
bool r = c.get_blocks(0, 100 + 2 * CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, blocks);
CHECK_TEST_CONDITION(r);
std::vector<block> blocks(block_list.begin(), block_list.end());
//CHECK_EQ(expected_blockchain_height, blocks.size());
if (expected_blockchain_height != blocks.size()) LOG_ERROR ("oops");

View File

@ -96,10 +96,10 @@ bool gen_double_spend_base<concrete_test>::check_double_spend(cryptonote::core&
}
CHECK_NOT_EQ(invalid_index_value, m_invalid_block_index);
std::vector<cryptonote::block> block_list;
bool r = c.get_blocks(0, 100 + 2 * CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, block_list);
std::vector<cryptonote::block> blocks;
bool r = c.get_blocks(0, 100 + 2 * CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, blocks);
CHECK_TEST_CONDITION(r);
CHECK_TEST_CONDITION(m_last_valid_block == block_list.back());
CHECK_TEST_CONDITION(m_last_valid_block == blocks.back());
CHECK_EQ(concrete_test::expected_pool_txs_count, c.get_pool_transactions_count());
@ -108,7 +108,6 @@ bool gen_double_spend_base<concrete_test>::check_double_spend(cryptonote::core&
std::vector<cryptonote::block> chain;
map_hash2tx_t mtx;
std::vector<cryptonote::block> blocks(block_list.begin(), block_list.end());
r = find_block_chain(events, chain, mtx, get_block_hash(blocks.back()));
CHECK_TEST_CONDITION(r);
CHECK_EQ(concrete_test::expected_bob_balance, get_balance(bob_account, blocks, mtx));

View File

@ -163,9 +163,12 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
MAKE_GENESIS_BLOCK(events, blk_0, miner_account[creator], ts_start);
constexpr int block_major = 7;
constexpr int block_minor = 7;
// create 8 miner accounts, and have them mine the next 8 blocks
// they will have a coinbase with a single out that's pseudo rct
constexpr size_t n_coinbases = 8;
constexpr size_t n_coinbases = 48;
cryptonote::account_base miner_accounts[n_coinbases];
const cryptonote::block *prev_block = &blk_0;
cryptonote::block blocks[n_coinbases];
@ -175,7 +178,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
account_base &account = n < inputs ? miner_account[creator] : miner_accounts[n];
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blocks[n], *prev_block, account,
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
4, 4, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
block_major, block_minor, prev_block->timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0),
false, "Failed to generate block");
events.push_back(blocks[n]);
@ -193,7 +196,7 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
cryptonote::block blk;
CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk, blk_last, miner_accounts[0],
test_generator::bf_major_ver | test_generator::bf_minor_ver | test_generator::bf_timestamp | test_generator::bf_hf_version,
4, 4, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
block_major, block_minor, blk_last.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN * 2, // v2 has blocks twice as long
crypto::hash(), 0, transaction(), std::vector<crypto::hash>(), 0),
false, "Failed to generate block");
events.push_back(blk);
@ -478,196 +481,168 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
bool gen_multisig_tx_valid_22_1_2::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_22_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
return generate_with(events, 4, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 2, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_22_2_1::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 2, 2, {1}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 2, 2, {1}, NULL, NULL);
}
bool gen_multisig_tx_valid_33_1_23::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 3, 3, 1, {2, 3}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 3, 3, 1, {2, 3}, NULL, NULL);
}
bool gen_multisig_tx_valid_33_3_21::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 3, 3, 3, {2, 1}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 3, 3, 3, {2, 1}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_1_2::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 1, {2}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 3, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_1_3::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 1, {3}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 3, 1, {3}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_2_1::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 2, {1}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 3, 2, {1}, NULL, NULL);
}
bool gen_multisig_tx_valid_23_2_3::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 3, 2, {3}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 3, 2, {3}, NULL, NULL);
}
bool gen_multisig_tx_valid_45_1_234::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 4, 5, 1, {2, 3, 4}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 4, 5, 1, {2, 3, 4}, NULL, NULL);
}
bool gen_multisig_tx_valid_45_4_135_many_inputs::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 4, 5, 4, {1, 3, 5}, NULL, NULL);
return generate_with(events, 4, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 4, 5, 4, {1, 3, 5}, NULL, NULL);
}
bool gen_multisig_tx_valid_89_3_1245789::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 8, 9, 3, {1, 2, 4, 5, 7, 8, 9}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 8, 9, 3, {1, 2, 4, 5, 7, 8, 9}, NULL, NULL);
}
bool gen_multisig_tx_valid_24_1_2::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_24_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
return generate_with(events, 4, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 4, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_25_1_2::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_25_1_2_many_inputs::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
return generate_with(events, 4, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 2, 5, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_valid_48_1_234::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
}
bool gen_multisig_tx_valid_48_1_234_many_inputs::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 4, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
return generate_with(events, 4, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL);
}
bool gen_multisig_tx_invalid_22_1__no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 2, 1, {}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 2, 2, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_33_1__no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 3, 3, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_33_1_2_no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {2}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 3, 3, 1, {2}, NULL, NULL);
}
bool gen_multisig_tx_invalid_33_1_3_no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 3, 3, 1, {3}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 3, 3, 1, {3}, NULL, NULL);
}
bool gen_multisig_tx_invalid_23_1__no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 3, 1, {}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 2, 3, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_invalid_45_5_23_no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 4, 5, 5, {2, 3}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 4, 5, 5, {2, 3}, NULL, NULL);
}
bool gen_multisig_tx_valid_24_1_no_signers::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 4, 1, {}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 2, 4, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_valid_25_1_no_signers::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 2, 5, 1, {}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 2, 5, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_valid_48_1_no_signers::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 4, 8, 1, {}, NULL, NULL);
}
bool gen_multisig_tx_valid_48_1_23_no_threshold::generate(std::vector<test_event_entry>& events) const
{
const size_t mixin = 4;
const uint64_t amount_paid = 10000;
return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {2, 3}, NULL, NULL);
return generate_with(events, 2, CRYPTONOTE_TX_DEFAULT_MIX, amount_paid, false, 4, 8, 1, {2, 3}, NULL, NULL);
}

View File

@ -82,7 +82,7 @@ private:
template<>
struct get_test_options<gen_multisig_tx_validation_base> {
const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(4, 1), std::make_pair(0, 0)};
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = {std::make_pair(7, 0)};
const cryptonote::test_options test_options = {
hard_forks
};

View File

@ -81,7 +81,7 @@ private:
template<>
struct get_test_options<gen_rct_tx_validation_base> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(0, 0)};
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65)};
const cryptonote::test_options test_options = {
hard_forks
};

View File

@ -262,6 +262,8 @@ class linear_chain_generator
void set_sn_list(const sn_list& list) { sn_list_ = list; }
QuorumState get_quorum_idxs(const cryptonote::block& block) const;
QuorumState get_quorum_idxs(uint64_t height) const;
cryptonote::transaction create_deregister_tx(const crypto::public_key& pk, uint64_t height, const std::vector<sn_idx>& voters, uint64_t fee = 0) const;
@ -400,10 +402,8 @@ cryptonote::block linear_chain_generator::create_block_on_fork(const cryptonote:
return blk;
}
QuorumState linear_chain_generator::get_quorum_idxs(uint64_t height) const
QuorumState linear_chain_generator::get_quorum_idxs(const cryptonote::block& block) const
{
const auto block = blocks_.at(height);
if (sn_list_.size() <= service_nodes::QUORUM_SIZE) {
std::cerr << "Not enough service nodes\n";
return {};
@ -436,6 +436,12 @@ QuorumState linear_chain_generator::get_quorum_idxs(uint64_t height) const
return quorum;
}
QuorumState linear_chain_generator::get_quorum_idxs(uint64_t height) const
{
const auto block = blocks_.at(height);
return get_quorum_idxs(block);
}
cryptonote::transaction linear_chain_generator::create_tx(const cryptonote::account_base& miner,
const cryptonote::account_base& acc,
uint64_t amount,
@ -848,3 +854,116 @@ bool test_deregister_safety_buffer::generate(std::vector<test_event_entry> &even
return true;
}
//-----------------------------------------------------------------------------------------------------
//---------------------------------- Test Deregisters on Split ----------------------------------------
//-----------------------------------------------------------------------------------------------------
// Test a chain that is equal up to a certain point, splits, and 1 of the chains forms a block that has a deregister
// for Service Node A. Chain 2 receives a deregister for Service Node A with a different permutation of votes than
// the one known in Chain 1 and is sitting in the mempool. On reorg, Chain 1 should become the canonical chain and
// those sitting on Chain 2 should not have problems switching over.
test_deregisters_on_split::test_deregisters_on_split()
{
REGISTER_CALLBACK_METHOD(test_deregisters_on_split, mark_invalid_tx);
REGISTER_CALLBACK("test_on_split", test_deregisters_on_split::test_on_split);
}
//-----------------------------------------------------------------------------------------------------
bool test_deregisters_on_split::generate(std::vector<test_event_entry> &events)
{
linear_chain_generator gen(events);
gen.create_genesis_block();
gen.rewind_until_v9();
/// generate some outputs and unlock them
gen.rewind_blocks_n(20);
gen.rewind_blocks();
/// register 12 random service nodes
std::vector<cryptonote::transaction> reg_txs;
for (auto i = 0; i < 12; ++i) {
const auto sn = get_static_keys(i);
const auto tx = gen.create_registration_tx(gen.first_miner(), sn);
reg_txs.push_back(tx);
}
gen.create_block(reg_txs);
/// chain split
const auto pivot_block = gen.chain_head();
/// public key of the node to deregister (valid at the height of the pivot block)
const auto pk = gen.get_test_pk(0);
const auto pivot_height = gen.height();
/// Get a copy, so we can undo all the changes on reorg
const auto sn_list_before_split = gen.get_sn_list();
/// create deregistration A
auto quorumA = gen.get_quorum_idxs(pivot_block).voters;
quorumA.erase(quorumA.begin()); /// remove first voter
const auto dereg_A = gen.build_deregister(pk).with_voters(quorumA).with_height(pivot_height).build();
/// create deregistration on alt chain (B)
auto quorumB = gen.get_quorum_idxs(pivot_block).voters;
quorumB.erase(quorumB.begin() + 1); /// remove second voter
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, true);
const auto dereg_B = gen.build_deregister(pk).with_voters(quorumB).with_height(pivot_height).build(); /// events[68]
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, false);
/// continue main chain with deregister A
gen.create_block({dereg_A});
gen.set_sn_list(sn_list_before_split);
/// continue alt chain with deregister B
const auto alt_head = gen.create_block_on_fork(pivot_block, { dereg_B });
/// actually remove pk form the local service node list
gen.deregister(pk);
/// one more block on alt chain to switch
gen.create_block_on_fork(alt_head);
DO_CALLBACK(events, "test_on_split");
return true;
}
//-----------------------------------------------------------------------------------------------------
/// Check that the deregister transaction is the one from the alternative branch
bool test_deregisters_on_split::test_on_split(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry> &events)
{
DEFINE_TESTS_ERROR_CONTEXT("test_deregisters_on_split::test_on_split");
/// obtain the expected deregister from events
const size_t dereg_idx = 68;
auto dereg_tx = boost::get<cryptonote::transaction>(events.at(dereg_idx));
CHECK_AND_ASSERT_MES(dereg_tx.is_deregister, false, "event is not a deregister transaction");
const auto expected_tx_hash = get_transaction_hash(dereg_tx);
/// find a deregister transaction in the blockchain
std::vector<block> blocks;
bool r = c.get_blocks(0, 1000, blocks);
CHECK_TEST_CONDITION(r);
map_hash2tx_t mtx;
std::vector<cryptonote::block> chain;
r = find_block_chain(events, chain, mtx, get_block_hash(blocks.back()));
CHECK_TEST_CONDITION(r);
/// get the second last block; it contains the deregister
const auto blk = blocks[blocks.size() - 2];
/// find the deregister tx:
const auto found_tx_hash = std::find_if(blk.tx_hashes.begin(), blk.tx_hashes.end(), [&mtx](const crypto::hash& hash) {
return mtx.at(hash)->is_deregister;
});
CHECK_TEST_CONDITION(found_tx_hash != blk.tx_hashes.end());
/// check that it is the expected one
CHECK_EQ(*found_tx_hash, expected_tx_hash);
return true;
}

View File

@ -34,7 +34,19 @@
/************************************************************************/
/* */
/************************************************************************/
class gen_service_nodes : public test_chain_unit_base
class test_service_nodes_base : public test_chain_unit_base {};
template<>
struct get_test_options<test_service_nodes_base>
{
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = { std::make_pair(7, 0),
std::make_pair(8, 1),
std::make_pair(9, 2) };
const cryptonote::test_options test_options = { hard_forks };
};
class gen_service_nodes : public test_service_nodes_base
{
public:
gen_service_nodes();
@ -45,31 +57,18 @@ private:
cryptonote::keypair m_alice_service_node_keys;
};
template<>
struct get_test_options<gen_service_nodes> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(7, 0), std::make_pair(8, 1), std::make_pair(9, 2), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks
};
};
template<> struct get_test_options<gen_service_nodes>: public get_test_options<test_service_nodes_base> {};
class test_prefer_deregisters : public test_chain_unit_base
class test_prefer_deregisters : public test_service_nodes_base
{
public:
test_prefer_deregisters();
bool generate(std::vector<test_event_entry> &events);
bool check_prefer_deregisters(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry> &events);
};
template<> struct get_test_options<test_prefer_deregisters>: public get_test_options<test_service_nodes_base> {};
template<>
struct get_test_options<test_prefer_deregisters> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(7, 0), std::make_pair(8, 1), std::make_pair(9, 2), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks
};
};
class test_zero_fee_deregister : public test_chain_unit_base
class test_zero_fee_deregister : public test_service_nodes_base
{
size_t m_invalid_tx_index;
@ -94,15 +93,9 @@ public:
}
};
template<>
struct get_test_options<test_zero_fee_deregister> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(7, 0), std::make_pair(8, 1), std::make_pair(9, 2), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks
};
};
template<> struct get_test_options<test_zero_fee_deregister>: public get_test_options<test_service_nodes_base> {};
class test_deregister_safety_buffer : public test_chain_unit_base
class test_deregister_safety_buffer : public test_service_nodes_base
{
size_t m_invalid_tx_index;
@ -128,10 +121,34 @@ public:
}
};
template<>
struct get_test_options<test_deregister_safety_buffer> {
const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(7, 0), std::make_pair(8, 1), std::make_pair(9, 2), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks
};
template<> struct get_test_options<test_deregister_safety_buffer>: public get_test_options<test_service_nodes_base> {};
class test_deregisters_on_split : public test_service_nodes_base
{
size_t m_invalid_tx_index;
public:
test_deregisters_on_split();
bool generate(std::vector<test_event_entry>& events);
bool test_on_split(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
bool mark_invalid_tx(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
{
m_invalid_tx_index = ev_index + 1;
return true;
}
bool check_tx_verification_context(const cryptonote::tx_verification_context& tvc,
bool tx_added,
size_t event_idx,
const cryptonote::transaction& /*tx*/)
{
if (m_invalid_tx_index == event_idx)
return tvc.m_verifivation_failed;
else
return !tvc.m_verifivation_failed && tx_added;
}
};
template<> struct get_test_options<test_deregisters_on_split>: public get_test_options<test_service_nodes_base> {};

View File

@ -79,7 +79,7 @@ private:
template<>
struct get_test_options<gen_v2_tx_validation_base> {
const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(0, 0)};
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = {std::make_pair(1, 0), std::make_pair(2, 1)};
const cryptonote::test_options test_options = {
hard_forks
};