From 2aa302f69a8c1831f3baf9d3cb82f173d6c977fc Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 3 Jun 2023 04:03:35 +0200 Subject: [PATCH 01/18] total number of HFs + "==" and "!=" for hard_forks_descriptor --- src/currency_core/core_runtime_config.h | 12 +++++++++++- src/currency_core/currency_config.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/currency_core/core_runtime_config.h b/src/currency_core/core_runtime_config.h index 583add64..31472800 100644 --- a/src/currency_core/core_runtime_config.h +++ b/src/currency_core/core_runtime_config.h @@ -13,7 +13,7 @@ namespace currency { struct hard_forks_descriptor { - constexpr static size_t m_total_count = 5; + constexpr static size_t m_total_count = ZANO_HARDFORKS_TOTAL; std::array m_height_the_hardfork_n_active_after; hard_forks_descriptor() @@ -81,6 +81,16 @@ namespace currency { return HF3_BLOCK_MINOR_VERSION; } + + bool operator==(const hard_forks_descriptor& rhs) const + { + return m_height_the_hardfork_n_active_after == rhs.m_height_the_hardfork_n_active_after; + } + + bool operator!=(const hard_forks_descriptor& rhs) const + { + return ! operator==(rhs); + } }; diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index b559d696..3a8876a6 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -266,6 +266,7 @@ #define ZANO_HARDFORK_02 2 #define ZANO_HARDFORK_03 3 #define ZANO_HARDFORK_04_ZARCANUM 4 +#define ZANO_HARDFORKS_TOTAL 5 From 30a54790a6028817f1747e0e7ae2f585be1b26de Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 3 Jun 2023 04:05:12 +0200 Subject: [PATCH 02/18] useful warnings and other logging improvements --- src/currency_core/currency_basic_backward_comp.inl | 7 ++++--- src/currency_core/currency_format_utils.cpp | 4 ++++ src/currency_core/tx_pool.cpp | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/currency_core/currency_basic_backward_comp.inl b/src/currency_core/currency_basic_backward_comp.inl index 1dd09309..7dffea0e 100644 --- a/src/currency_core/currency_basic_backward_comp.inl +++ b/src/currency_core/currency_basic_backward_comp.inl @@ -94,10 +94,11 @@ bool transition_convert(const transaction_current_t& from, transaction_v1& to) { if (s.type() == typeid(NLSAG_sig)) { - to.signatures.push_back(boost::get(s).s); ; - }else + to.signatures.push_back(boost::get(s).s); + } + else { - throw std::runtime_error("Unexpected type in signature_v"); + throw std::runtime_error(std::string("Unexpected type in tx.signatures during transition_convert: ") + s.type().name()); } } return true; diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 946595db..19cbd0a2 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2224,6 +2224,10 @@ namespace currency } } + if (zc_inputs_count != 0 && tx.version <= TRANSACTION_VERSION_PRE_HF4) + { + LOG_PRINT_YELLOW("WARNING: tx v1 should not use ZC inputs", LOG_LEVEL_0); + } // // OUTs diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 8fcca00f..527dc76a 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -945,8 +945,8 @@ namespace currency return "(no transactions, the pool is empty)"; // sort output by receive time txs.sort([](const std::pair& lhs, const std::pair& rhs) -> bool { return lhs.second.receive_time < rhs.second.receive_time; }); - ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL; - // 1234 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES + ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL; + // 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES size_t i = 0; for (auto& tx : txs) { From 363d1bc3168d89d15c0f491666023cc7d8fbaddb Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 3 Jun 2023 04:12:01 +0200 Subject: [PATCH 03/18] coretests: redesigned test environment to allow individual tests to be conducted against various activated hardforks --- tests/core_tests/chaingen.h | 3 + tests/core_tests/chaingen_main.cpp | 170 ++++++++++++++++++++++++-- tests/core_tests/wallet_tests_basic.h | 2 + 3 files changed, 168 insertions(+), 7 deletions(-) diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 216643a5..e59d3e79 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -255,11 +255,14 @@ public: void set_core_proxy(std::shared_ptr) { /* do nothing */ } uint64_t get_tx_version_from_events(const std::vector &events) const; + virtual void on_test_constructed() {} // called right after test class is constructed by the chaingen void on_test_generator_created(test_generator& generator) const; // tests can override this for special initialization currency::core_runtime_config get_runtime_info_for_core() const; // tests can override this for special initialization void set_hardforks_for_old_tests(); + currency::hard_forks_descriptor& get_hardforks() { return m_hardforks; } + const currency::hard_forks_descriptor& get_hardforks() const { return m_hardforks; } private: callbacks_map m_callbacks; diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 1ae27e47..eaa18dae 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -39,6 +39,7 @@ namespace test_generator::set_test_gentime_settings_default(); \ std::vector events; \ genclass g; \ + g.on_test_constructed(); \ g.generate(events); \ if (!tools::serialize_obj_to_file(events, filename)) \ { \ @@ -54,6 +55,95 @@ namespace return 1; \ } + +std::vector parse_hardfork_str_mask(std::string s /* intentionally passing by value */) +{ + // "*" -> 0, 1, 2, ..., ZANO_HARDFORKS_TOTAL-1 + // "2-4,0" -> 2, 3, 4, 0 + // "1, 3-*" -> 1, 3, 4, ..., ZANO_HARDFORKS_TOTAL-1 + + std::vector result; + + auto error_result = []() -> std::vector { return std::vector(); }; + auto all_hardforks = []() -> std::vector { std::vector r; for(size_t i = 0; i < ZANO_HARDFORKS_TOTAL; ++i) r.push_back(i); return r; }; + + // remove all spaces + s.erase(std::remove_if(s.begin(), s.end(), [](char c){ return std::isspace(static_cast(c)); }), s.end()); + std::vector ranges; + boost::split(ranges, s, boost::is_any_of(",")); + for(auto& range : ranges) + { + std::vector segments; + boost::split(segments, range, boost::is_any_of("-")); + if (segments.size() == 1) + { + if (segments.front() == "*") + return all_hardforks(); + size_t hfid = SIZE_MAX; + if (!epee::string_tools::string_to_num_fast(segments.front(), (int64_t&)hfid) || hfid == SIZE_MAX || hfid >= ZANO_HARDFORKS_TOTAL) + return error_result(); + result.push_back(hfid); + } + else if (segments.size() == 2) + { + if (segments.front() == "*") + return all_hardforks(); + + size_t hfid_a = SIZE_MAX; + if (!epee::string_tools::string_to_num_fast(segments.front(), (int64_t&)hfid_a) || hfid_a == SIZE_MAX || hfid_a >= ZANO_HARDFORKS_TOTAL) + return error_result(); + + size_t hfid_b = SIZE_MAX; + if (segments.back() == "*") + hfid_b = ZANO_HARDFORKS_TOTAL - 1; + else + { + if (!epee::string_tools::string_to_num_fast(segments.back(), (int64_t&)hfid_b)) + hfid_b = SIZE_MAX; + } + if (hfid_b == SIZE_MAX || hfid_b >= ZANO_HARDFORKS_TOTAL || hfid_b < hfid_a) + return error_result(); + for(size_t i = hfid_a; i <= hfid_b; ++i) + result.push_back(i); + if (segments.back() == "*") + return result; // don't keep parsing if the last range was ?-* + } + else // i.e. segments.size() == 0 || segments.size() > 2 + return error_result(); + } + return result; +} + +bool test_parse_hardfork_str_mask() +{ + static_assert(ZANO_HARDFORKS_TOTAL >= 5, "this test was made in assumption that this condition holds"); + auto v_range = [](size_t a, size_t b) -> std::vector { std::vector r; for(size_t i = a; i <= b; ++i) r.push_back(i); return r; }; + auto v_concat = [](const std::vector& a, const std::vector& b) -> std::vector { std::vector r = a; r.insert(r.end(), b.begin(), b.end()); }; + const std::vector res_empty; + const std::vector res_all_hf = v_range(0, ZANO_HARDFORKS_TOTAL - 1); + std::string hf_total_num_str_m_1 = epee::string_tools::num_to_string_fast(ZANO_HARDFORKS_TOTAL - 1); + std::string hf_total_num_str = epee::string_tools::num_to_string_fast(ZANO_HARDFORKS_TOTAL); + + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("") == res_empty, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("*") == res_all_hf, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("1,2") == v_range(1, 2), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("0,*, 3") == res_all_hf, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("1-4") == v_range(1, 4), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("4-1") == res_empty, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("3-1,2") == res_empty, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("1,2-1") == res_empty, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("0, 2 - 2") == std::vector({0, 2}), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("2-*") == v_range(2, ZANO_HARDFORKS_TOTAL - 1), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask(" 2-*, 1") == v_range(2, ZANO_HARDFORKS_TOTAL - 1), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("2- *,3") == v_range(2, ZANO_HARDFORKS_TOTAL - 1), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask("1,3,2") == std::vector({1, 3, 2}), false, ""); + + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask(hf_total_num_str_m_1) == std::vector({ZANO_HARDFORKS_TOTAL - 1}), false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask(hf_total_num_str) == res_empty, false, ""); + CHECK_AND_ASSERT_MES(parse_hardfork_str_mask(std::string("2-") + hf_total_num_str) == res_empty, false, ""); + return true; +} + bool clean_data_directory() { std::string config_folder = command_line::get_arg(g_vm, command_line::arg_data_dir); @@ -102,7 +192,7 @@ bool clean_data_directory() } template -bool generate_and_play(const char* const genclass_name) +bool generate_and_play(const char* const genclass_name, size_t hardfork_id = SIZE_MAX) { std::vector events; bool generated = false; @@ -117,11 +207,37 @@ bool generate_and_play(const char* const genclass_name) test_core_time::init(); test_generator::set_test_gentime_settings_default(); genclass g; + + static const test_chain_unit_base tcub; + bool has_non_default_hardforks = g.get_hardforks() != tcub.get_hardforks(); // compare with the defaults + currency::hard_forks_descriptor hfd_local{}; + if (hardfork_id != SIZE_MAX) + { + static test_chain_unit_base tcub; + if (has_non_default_hardforks) // compare with the defaults + { + LOG_ERROR(ENDL << "hardforks setting have been changed in ctor of " << genclass_name << " test" << ENDL << ENDL); + return false; + } + g.get_hardforks().clear(); + g.get_hardforks().set_hardfork_height(hardfork_id, 1 /* <- height_the_hardfork_is_active_after */); + } + hfd_local = g.get_hardforks(); // save a copy for the safety checking at the end + + g.on_test_constructed(); + try { generated = g.generate(events); if (generated) { + std::cout << concolor::normal << events.size() << " events generated successfully" << std::endl; + if (has_non_default_hardforks || g.get_hardforks() != tcub.get_hardforks()) + { + size_t configure_core_events_count = std::count_if(events.begin(), events.end(), [](auto& ev){ return ev.type() == typeid(callback_entry) && boost::get(ev).callback_name == "configure_core"; }); + CHECK_AND_ASSERT_THROW_MES(configure_core_events_count != 0, "Test " << genclass_name << " has non-default hardfork settings and therefore must use 'configure_core' callback"); + } + std::cout << concolor::bright_white << std::string(100, '=') << std::endl << "#TEST# >>>> " << genclass_name << " <<<< start replaying events" << std::endl << std::string(100, '=') << concolor::normal << std::endl; @@ -131,11 +247,18 @@ bool generate_and_play(const char* const genclass_name) } catch (const std::exception& ex) { - LOG_ERROR("got an exception during " << genclass_name << (generated ? " replaying: " : " generation: ") << ex.what()); + LOG_ERROR(">>>>> got an exception during " << genclass_name << (generated ? " replaying: " : " generation: ") << ex.what()); } catch (...) { - LOG_ERROR("got an unknown exception during " << genclass_name << (generated ? " replaying" : " generation")); + LOG_ERROR(">>>>> got an unknown exception during " << genclass_name << (generated ? " replaying" : " generation")); + } + + if (hardfork_id != SIZE_MAX && g.get_hardforks() != hfd_local) + { + // conflict detected: hardfork settings are either controlled by the test itself or by the chaingen + LOG_ERROR("hardforks setting have been changed during generation or execution of test " << genclass_name); + result = false; } if (result) @@ -181,6 +304,7 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_ test_core_time::init(); test_generator::set_test_gentime_settings_default(); genclass g; + g.on_test_constructed(); try { r = g.generate(events); @@ -294,6 +418,34 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_ tests_running_time.push_back(std::make_pair(testname, t)); \ } + + +#define GENERATE_AND_PLAY_HF(genclass, hardfork_str_mask) \ + if((!postponed_tests.count(#genclass) && run_single_test.empty()) || (!run_single_test.empty() && std::string::npos != std::string(#genclass).find(run_single_test))) \ + { \ + std::vector hardforks = parse_hardfork_str_mask(hardfork_str_mask); \ + CHECK_AND_ASSERT_MES(!hardforks.empty(), false, "invalid hardforks mask: " << hardfork_str_mask); \ + for(size_t hfid : hardforks) \ + { \ + std::string tns = std::string(#genclass) + " @ HF " + epee::string_tools::num_to_string_fast(hfid); \ + const char* testname = tns.c_str(); \ + TIME_MEASURE_START_MS(t); \ + ++tests_count; \ + if (!generate_and_play(testname, hfid)) \ + { \ + failed_tests.insert(testname); \ + LOCAL_ASSERT(false); \ + if (stop_on_first_fail) \ + return 1; \ + } \ + TIME_MEASURE_FINISH_MS(t); \ + tests_running_time.push_back(std::make_pair(testname, t)); \ + } \ + ++unique_tests_count; \ + } + + + //#define GENERATE_AND_PLAY(genclass) GENERATE_AND_PLAY_INTERMITTED_BY_BLOCKCHAIN_SAVELOAD(genclass) @@ -738,6 +890,7 @@ int main(int argc, char* argv[]) } size_t tests_count = 0; + size_t unique_tests_count = 0; size_t serious_failures_count = 0; std::set failed_tests; std::string tests_folder = command_line::get_arg(g_vm, arg_test_data_path); @@ -774,6 +927,7 @@ int main(int argc, char* argv[]) CALL_TEST("check_allowed_types_in_variant_container() test", check_allowed_types_in_variant_container_test); CALL_TEST("check_u8_str_case_funcs", check_u8_str_case_funcs); CALL_TEST("chec_u8_str_matching", chec_u8_str_matching); + CALL_TEST("test_parse_hardfork_str_mask", test_parse_hardfork_str_mask); } //CALL_TEST("check_hash_and_difficulty_monte_carlo_test", check_hash_and_difficulty_monte_carlo_test); // it's rather an experiment with unclean results than a solid test, for further research... @@ -1134,10 +1288,12 @@ int main(int argc, char* argv[]) std::cout << (serious_failures_count == 0 ? concolor::green : concolor::magenta); std::cout << "\nREPORT:\n"; - std::cout << " Test run: " << tests_count << std::endl; - std::cout << " Failures: " << serious_failures_count << " (postponed failures: " << failed_postponed_tests_count << ")" << std::endl; - std::cout << " Postponed: " << postponed_tests.size() << std::endl; - std::cout << " Total time: " << total_time / 1000 << " s. (" << (tests_count > 0 ? total_time / tests_count : 0) << " ms per test in average)" << std::endl; + std::cout << " Unique tests run: " << unique_tests_count << std::endl; + std::cout << " Total tests run: " << tests_count << std::endl; + + std::cout << " Failures: " << serious_failures_count << " (postponed failures: " << failed_postponed_tests_count << ")" << std::endl; + std::cout << " Postponed: " << postponed_tests.size() << std::endl; + std::cout << " Total time: " << total_time / 1000 << " s. (" << (tests_count > 0 ? total_time / tests_count : 0) << " ms per test in average)" << std::endl; if (!failed_tests.empty()) { std::cout << "FAILED/POSTPONED TESTS:\n"; diff --git a/tests/core_tests/wallet_tests_basic.h b/tests/core_tests/wallet_tests_basic.h index 425c81f6..f90b0f4c 100644 --- a/tests/core_tests/wallet_tests_basic.h +++ b/tests/core_tests/wallet_tests_basic.h @@ -17,6 +17,8 @@ struct wallet_test : virtual public test_chain_unit_enchanced bool check_balance_via_build_wallets(currency::core& c, size_t ev_index, const std::vector& events); bool check_balance(currency::core& c, size_t ev_index, const std::vector& events); + void on_test_constructed() override { on_test_generator_created(this->generator); } + static std::string get_test_account_name_by_id(size_t acc_id); protected: From 6efe47f69cd21b73cd60c8370064d55260c2895c Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 3 Jun 2023 04:15:14 +0200 Subject: [PATCH 04/18] coretests: eliminated unnecessary multiple inheritance from hard fork 2 tests --- tests/core_tests/hard_fork_2.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/core_tests/hard_fork_2.h b/tests/core_tests/hard_fork_2.h index caeb0eaf..849fc679 100644 --- a/tests/core_tests/hard_fork_2.h +++ b/tests/core_tests/hard_fork_2.h @@ -7,7 +7,7 @@ #include "wallet_tests_basic.h" #include "random_helper.h" -struct hard_fork_2_base_test : virtual public test_chain_unit_enchanced +struct hard_fork_2_base_test : public wallet_test { hard_fork_2_base_test(size_t hardfork_02_height); hard_fork_2_base_test(size_t hardfork_01_height, size_t hardfork_02_height); @@ -18,14 +18,14 @@ struct hard_fork_2_base_test : virtual public test_chain_unit_enchanced size_t m_hardfork_03_height; }; -struct hard_fork_2_tx_payer_in_wallet : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_tx_payer_in_wallet : public hard_fork_2_base_test { hard_fork_2_tx_payer_in_wallet(); bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; -struct hard_fork_2_tx_receiver_in_wallet : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_tx_receiver_in_wallet : public hard_fork_2_base_test { hard_fork_2_tx_receiver_in_wallet(); bool generate(std::vector& events) const; @@ -34,21 +34,21 @@ struct hard_fork_2_tx_receiver_in_wallet : public wallet_test, public hard_fork_ mutable uint64_t m_alice_start_balance; }; -struct hard_fork_2_tx_extra_alias_entry_in_wallet : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_tx_extra_alias_entry_in_wallet : public hard_fork_2_base_test { hard_fork_2_tx_extra_alias_entry_in_wallet(); bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; -struct hard_fork_2_auditable_addresses_basics : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_auditable_addresses_basics : public hard_fork_2_base_test { hard_fork_2_auditable_addresses_basics(); bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; -struct hard_fork_2_no_new_structures_before_hf : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_no_new_structures_before_hf : public hard_fork_2_base_test { using hard_fork_2_base_test::check_block_verification_context; // this is necessary for correct work of do_check_block_verification_context, consider rafactoring @@ -58,7 +58,7 @@ struct hard_fork_2_no_new_structures_before_hf : public wallet_test, public hard }; template -struct hard_fork_2_awo_wallets_basic_test : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_awo_wallets_basic_test : public hard_fork_2_base_test { hard_fork_2_awo_wallets_basic_test(); bool generate(std::vector& events) const; @@ -66,7 +66,7 @@ struct hard_fork_2_awo_wallets_basic_test : public wallet_test, public hard_fork }; template -struct hard_fork_2_alias_update_using_old_tx : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_alias_update_using_old_tx : public hard_fork_2_base_test { hard_fork_2_alias_update_using_old_tx(); bool generate(std::vector& events) const; @@ -76,7 +76,7 @@ struct hard_fork_2_alias_update_using_old_tx : public wallet_test, public hard_f }; template -struct hard_fork_2_incorrect_alias_update : public wallet_test, public hard_fork_2_base_test +struct hard_fork_2_incorrect_alias_update : public hard_fork_2_base_test { hard_fork_2_incorrect_alias_update(); bool generate(std::vector& events) const; From ed9741e3cdab0f9d87e958e1e3ccdda7f04263ad Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 3 Jun 2023 04:21:12 +0200 Subject: [PATCH 05/18] coretests: improved gen_wallet_save_load_and_balance test to uncover a bug in wallet save-load process for HF4 + fixed incorrect balance checking for some old wallet tests --- tests/core_tests/wallet_tests.cpp | 52 ++++++++++++++++++++++--------- tests/core_tests/wallet_tests.h | 2 +- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index 8abd0ecf..36738065 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -432,7 +432,7 @@ bool gen_wallet_unconfirmed_tx_from_tx_pool::generate(std::vector& e generator.construct_genesis_block(blk_0, miner_acc, test_core_time::get_time()); events.push_back(blk_0); + DO_CALLBACK(events, "configure_core"); + // create gen-time test wallets for accounts CREATE_TEST_WALLET(miner_wlt, miner_acc, blk_0); CREATE_TEST_WALLET(alice_wlt, alice_acc, blk_0); @@ -473,7 +475,7 @@ bool gen_wallet_save_load_and_balance::generate(std::vector& e // put the transaction into a block MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); - // 0 10 11 21 22 <- blockchain height (assuming CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 10) + // 0 10 11 21 23 <- blockchain height (assuming CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 10) // (0 )... (0r)- (1 )... (1r)- <- main chain // tx_0 <- txs // \- (2 )...........(2r) <- alt chain @@ -487,12 +489,12 @@ bool gen_wallet_save_load_and_balance::generate(std::vector& e if (!check_balance_via_wallet(*alice_wlt.get(), "alice", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0)) return false; - // load wallet from file and re-chech the balance - DO_CALLBACK(events, "c2_load_refresh_check_balance"); + // load wallet from file, re-chech the balance, store, load again, re-reck again, make tx, make block, check balance, store wallet + DO_CALLBACK(events, "c2"); // switch the chain, reload and re-check the wallet - REWIND_BLOCKS_N_WITH_TIME(events, blk_2r, blk_0r, miner_acc, WALLET_DEFAULT_TX_SPENDABLE_AGE + 2); - REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_2r, WALLET_DEFAULT_TX_SPENDABLE_AGE + 2); + REWIND_BLOCKS_N_WITH_TIME(events, blk_2r, blk_0r, miner_acc, WALLET_DEFAULT_TX_SPENDABLE_AGE + 3); + REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_2r, WALLET_DEFAULT_TX_SPENDABLE_AGE + 3); alice_wlt->scan_tx_pool(has_aliases); if (!check_balance_via_wallet(*alice_wlt.get(), "alice", MK_TEST_COINS(2000), 0, 0, MK_TEST_COINS(2000), 0)) // tx_0 moved to the pool, so its money in "awaiting_in" bucket return false; @@ -513,7 +515,7 @@ bool gen_wallet_save_load_and_balance::c1_check_balance_and_store(currency::core bool has_alias; alice_wlt->scan_tx_pool(has_alias); - check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, 0, MK_TEST_COINS(2000), 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, 0, MK_TEST_COINS(2000), 0), false, ""); alice_wlt->reset_password(g_wallet_password); alice_wlt->store(g_wallet_filename); @@ -521,11 +523,12 @@ bool gen_wallet_save_load_and_balance::c1_check_balance_and_store(currency::core return true; } -bool gen_wallet_save_load_and_balance::c2_load_refresh_check_balance(currency::core& c, size_t ev_index, const std::vector& events) +bool gen_wallet_save_load_and_balance::c2(currency::core& c, size_t ev_index, const std::vector& events) { std::shared_ptr alice_wlt(new tools::wallet2); alice_wlt->load(g_wallet_filename, g_wallet_password); alice_wlt->set_core_proxy(m_core_proxy); + alice_wlt->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config()); size_t blocks_fetched = 0; bool received_money; @@ -533,7 +536,25 @@ bool gen_wallet_save_load_and_balance::c2_load_refresh_check_balance(currency::c alice_wlt->refresh(blocks_fetched, received_money, atomic_false); CHECK_AND_ASSERT_MES(blocks_fetched == WALLET_DEFAULT_TX_SPENDABLE_AGE + 1, false, "Incorrect numbers of blocks fetched"); - check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0), false, ""); + alice_wlt->store(g_wallet_filename); + + ////// save - load //////// + + alice_wlt.reset(new tools::wallet2); + alice_wlt->load(g_wallet_filename, g_wallet_password); + alice_wlt->set_core_proxy(m_core_proxy); + alice_wlt->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config()); + + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0), false, ""); + + alice_wlt->transfer(MK_TEST_COINS(1000) - TESTS_DEFAULT_FEE, m_accounts[MINER_ACC_IDX].get_public_address()); + + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(1000), 0, 0, 0, MK_TEST_COINS(1000) - TESTS_DEFAULT_FEE), false, ""); + + bool r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed"); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count()); alice_wlt->store(g_wallet_filename); @@ -545,17 +566,18 @@ bool gen_wallet_save_load_and_balance::c3_load_refresh_check_balance(currency::c std::shared_ptr alice_wlt(new tools::wallet2); alice_wlt->load(g_wallet_filename, g_wallet_password); alice_wlt->set_core_proxy(m_core_proxy); + alice_wlt->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config()); size_t blocks_fetched = 0; bool received_money; std::atomic atomic_false = ATOMIC_VAR_INIT(false); alice_wlt->refresh(blocks_fetched, received_money, atomic_false); - CHECK_AND_ASSERT_MES(blocks_fetched == WALLET_DEFAULT_TX_SPENDABLE_AGE + 2, false, "Incorrect numbers of blocks fetched"); + CHECK_AND_ASSERT_MES(blocks_fetched == WALLET_DEFAULT_TX_SPENDABLE_AGE + 3, false, "Incorrect numbers of blocks fetched"); bool has_alias; alice_wlt->scan_tx_pool(has_alias); - check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, 0, MK_TEST_COINS(2000), 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(3000), 0, 0, MK_TEST_COINS(2000), MK_TEST_COINS(1000) - TESTS_DEFAULT_FEE), false, ""); return true; } @@ -616,7 +638,7 @@ bool gen_wallet_mine_pos_block::c1(currency::core& c, size_t ev_index, const std alice_wlt->refresh(blocks_fetched, received_money, atomic_false); CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + WALLET_DEFAULT_TX_SPENDABLE_AGE + 1, false, "Incorrect numbers of blocks fetched"); - check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0), false, ""); alice_wlt->try_mint_pos(); @@ -628,7 +650,7 @@ bool gen_wallet_mine_pos_block::c1(currency::core& c, size_t ev_index, const std bool r = c.get_blockchain_storage().get_top_block(top_block); CHECK_AND_ASSERT_MES(r && is_pos_block(top_block), false, "get_top_block failed or smth goes wrong"); uint64_t top_block_reward = get_outs_money_amount(top_block.miner_tx); - check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0), false, ""); alice_wlt->reset_password(g_wallet_password); alice_wlt->store(g_wallet_filename); @@ -3390,7 +3412,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5, false, "Incorrect numbers of blocks fetched"); miner_wlt->set_pos_mint_packing_size(4); - check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0), false, ""); miner_wlt->try_mint_pos(); @@ -3402,7 +3424,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde bool r = c.get_blockchain_storage().get_top_block(top_block); CHECK_AND_ASSERT_MES(r && is_pos_block(top_block), false, "get_top_block failed or smth goes wrong"); uint64_t top_block_reward = get_outs_money_amount(top_block.miner_tx); - check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0), false, ""); miner_wlt->reset_password(g_wallet_password); miner_wlt->store(g_wallet_filename); diff --git a/tests/core_tests/wallet_tests.h b/tests/core_tests/wallet_tests.h index eb54960b..ac5569d5 100644 --- a/tests/core_tests/wallet_tests.h +++ b/tests/core_tests/wallet_tests.h @@ -34,7 +34,7 @@ struct gen_wallet_save_load_and_balance : public wallet_test bool generate(std::vector& events) const; bool c1_check_balance_and_store(currency::core& c, size_t ev_index, const std::vector& events); - bool c2_load_refresh_check_balance(currency::core& c, size_t ev_index, const std::vector& events); + bool c2(currency::core& c, size_t ev_index, const std::vector& events); bool c3_load_refresh_check_balance(currency::core& c, size_t ev_index, const std::vector& events); }; From 6cab1f2e9ae6efa4875ba13dc14a4eded6d0aac3 Mon Sep 17 00:00:00 2001 From: sowle Date: Sun, 4 Jun 2023 20:50:31 +0200 Subject: [PATCH 06/18] coretests: minor fix for counting unique tests --- tests/core_tests/chaingen_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index eaa18dae..ce7eb0c8 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -390,6 +390,7 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_ { \ TIME_MEASURE_START_MS(t); \ ++tests_count; \ + ++unique_tests_count; \ if (!generate_and_play(#genclass)) \ { \ failed_tests.insert(#genclass); \ @@ -407,6 +408,7 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_ const char* testname = #genclass " (BC saveload)"; \ TIME_MEASURE_START_MS(t); \ ++tests_count; \ + ++unique_tests_count; \ if (!gen_and_play_intermitted_by_blockchain_saveload(testname)) \ { \ failed_tests.insert(testname); \ @@ -418,8 +420,6 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_ tests_running_time.push_back(std::make_pair(testname, t)); \ } - - #define GENERATE_AND_PLAY_HF(genclass, hardfork_str_mask) \ if((!postponed_tests.count(#genclass) && run_single_test.empty()) || (!run_single_test.empty() && std::string::npos != std::string(#genclass).find(run_single_test))) \ { \ From 1ec3bac95db5e347d12a78772e25c552ce7dfe5b Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 5 Jun 2023 18:19:39 +0200 Subject: [PATCH 07/18] coretests: adapted few tests to fit redesigned test environment (hardforks) --- tests/core_tests/alias_tests.cpp | 6 +- tests/core_tests/block_validation.cpp | 5 +- tests/core_tests/block_validation.h | 77 ++++++++-------------- tests/core_tests/chaingen_main.cpp | 58 ++++++++-------- tests/core_tests/checkpoints_tests.cpp | 6 +- tests/core_tests/multisig_wallet_tests.cpp | 5 +- 6 files changed, 65 insertions(+), 92 deletions(-) diff --git a/tests/core_tests/alias_tests.cpp b/tests/core_tests/alias_tests.cpp index 2a8ccb88..bdb68673 100644 --- a/tests/core_tests/alias_tests.cpp +++ b/tests/core_tests/alias_tests.cpp @@ -96,9 +96,6 @@ gen_alias_tests::gen_alias_tests() REGISTER_CALLBACK_METHOD(gen_alias_tests, check_height_not_changed); REGISTER_CALLBACK_METHOD(gen_alias_tests, check_height_changed); REGISTER_CALLBACK_METHOD(gen_alias_tests, check_too_many_aliases_registration); - - m_hardforks.set_hardfork_height(1, 0); - m_hardforks.set_hardfork_height(2, 0); } bool gen_alias_tests::generate(std::vector& events) const @@ -107,7 +104,6 @@ bool gen_alias_tests::generate(std::vector& events) const GENERATE_ACCOUNT(miner_account); // event index m_accounts.push_back(miner_account); MAKE_GENESIS_BLOCK(events, blk_0, preminer_account, test_core_time::get_time()); // 0 - set_hard_fork_heights_to_generator(generator); DO_CALLBACK(events, "configure_core"); // 1 MAKE_ACCOUNT(events, first_acc); // 2 MAKE_ACCOUNT(events, second_acc); // 3 @@ -874,6 +870,7 @@ bool gen_alias_reg_with_locked_money::generate(std::vector& ev GENERATE_ACCOUNT(alice); MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); currency::block& prev_block = blk_0; @@ -1155,6 +1152,7 @@ bool gen_alias_tx_no_outs::generate(std::vector& events) const uint64_t ts = test_core_time::get_time(); GENERATE_ACCOUNT(miner_acc); MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); events.push_back(miner_acc); REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 9b235d1b..2f337446 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2023 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -46,7 +46,8 @@ namespace #define BLOCK_VALIDATION_INIT_GENERATE() \ GENERATE_ACCOUNT(miner_account); \ - MAKE_GENESIS_BLOCK(events, blk_0, miner_account, 1338224400); + MAKE_GENESIS_BLOCK(events, blk_0, miner_account, 1338224400); \ + DO_CALLBACK(events, "configure_core"); //---------------------------------------------------------------------------------------------------------------------- // Tests diff --git a/tests/core_tests/block_validation.h b/tests/core_tests/block_validation.h index 74aaefa6..f4fce9ac 100644 --- a/tests/core_tests/block_validation.h +++ b/tests/core_tests/block_validation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2023 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -8,16 +8,11 @@ #include "chaingen.h" template -class gen_block_verification_base : public test_chain_unit_base +class gen_block_verification_base : public test_chain_unit_enchanced { public: gen_block_verification_base() { - m_hardforks.m_height_the_hardfork_n_active_after[1] = 1440; - m_hardforks.m_height_the_hardfork_n_active_after[2] = 1800; - m_hardforks.m_height_the_hardfork_n_active_after[3] = 1801; - m_hardforks.m_height_the_hardfork_n_active_after[4] = 50000000000; - REGISTER_CALLBACK("check_block_purged", gen_block_verification_base::check_block_purged); } @@ -29,143 +24,131 @@ public: return !bvc.m_verification_failed; } -// currency::core_runtime_config get_runtime_info_for_core() const -// { -// currency::core_runtime_config res = test_chain_unit_base::get_runtime_info_for_core(); -// -// } - bool check_block_purged(currency::core& c, size_t ev_index, const std::vector& events) { CHECK_TEST_CONDITION(invalid_block_idx < ev_index); CHECK_EQ(0, c.get_pool_transactions_count()); - CHECK_EQ(invalid_block_idx, c.get_current_blockchain_size()); + size_t invalid_block_height = invalid_block_idx - 1; // it's bad idea to use invalid_block_idx for both event index and block height, consider redisign -- sowle + CHECK_EQ(invalid_block_height, c.get_current_blockchain_size()); return true; } - //mutable currency::hard_forks_descriptor m_hardforks; }; template -struct gen_block_accepted_base : public test_chain_unit_base +struct gen_block_accepted_base : public test_chain_unit_enchanced { gen_block_accepted_base() { - m_hardforks.m_height_the_hardfork_n_active_after[1] = 1440; - m_hardforks.m_height_the_hardfork_n_active_after[2] = 1800; - m_hardforks.m_height_the_hardfork_n_active_after[3] = 1801; - m_hardforks.m_height_the_hardfork_n_active_after[4] = 50000000000; REGISTER_CALLBACK("check_block_accepted", gen_block_accepted_base::check_block_accepted); } bool check_block_accepted(currency::core& c, size_t /*ev_index*/, const std::vector& /*events*/) { - CHECK_EQ(0, c.get_pool_transactions_count()); CHECK_EQ(expected_blockchain_height, c.get_current_blockchain_size()); - return true; } }; -struct gen_block_big_major_version : public gen_block_verification_base<1> +struct gen_block_big_major_version : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_big_minor_version : public gen_block_accepted_base<2> +struct gen_block_big_minor_version : public gen_block_accepted_base<2 /* <- expected blockchain height */> { bool generate(std::vector& events) const; }; -struct gen_block_ts_not_checked : public gen_block_accepted_base +struct gen_block_ts_not_checked : public gen_block_accepted_base { bool generate(std::vector& events) const; }; -struct gen_block_ts_in_past : public gen_block_verification_base +struct gen_block_ts_in_past : public gen_block_verification_base { bool generate(std::vector& events) const; }; -struct gen_block_ts_in_future : public gen_block_verification_base<1> +struct gen_block_ts_in_future : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_invalid_prev_id : public gen_block_verification_base<1> +struct gen_block_invalid_prev_id : public gen_block_verification_base<2> { bool generate(std::vector& events) const; bool check_block_verification_context(const currency::block_verification_context& bvc, size_t event_idx, const currency::block& /*blk*/); }; -struct gen_block_invalid_nonce : public gen_block_verification_base<3> +struct gen_block_invalid_nonce : public gen_block_verification_base<4> { bool generate(std::vector& events) const; }; -struct gen_block_no_miner_tx : public gen_block_verification_base<1> +struct gen_block_no_miner_tx : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_unlock_time_is_low : public gen_block_verification_base<1> +struct gen_block_unlock_time_is_low : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_unlock_time_is_high : public gen_block_verification_base<1> +struct gen_block_unlock_time_is_high : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_unlock_time_is_timestamp_in_past : public gen_block_verification_base<1> +struct gen_block_unlock_time_is_timestamp_in_past : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_unlock_time_is_timestamp_in_future : public gen_block_verification_base<1> +struct gen_block_unlock_time_is_timestamp_in_future : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_height_is_low : public gen_block_verification_base<1> +struct gen_block_height_is_low : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_height_is_high : public gen_block_verification_base<1> +struct gen_block_height_is_high : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_miner_tx_has_2_tx_gen_in : public gen_block_verification_base<1> +struct gen_block_miner_tx_has_2_tx_gen_in : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_miner_tx_has_2_in : public gen_block_verification_base +struct gen_block_miner_tx_has_2_in : public gen_block_verification_base { bool generate(std::vector& events) const; }; -struct gen_block_miner_tx_with_txin_to_key : public gen_block_verification_base +struct gen_block_miner_tx_with_txin_to_key : public gen_block_verification_base { bool generate(std::vector& events) const; }; -struct gen_block_miner_tx_out_is_small : public gen_block_verification_base<1> +struct gen_block_miner_tx_out_is_small : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_miner_tx_out_is_big : public gen_block_verification_base<1> +struct gen_block_miner_tx_out_is_big : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_miner_tx_has_no_out : public gen_block_verification_base<1> +struct gen_block_miner_tx_has_no_out : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; @@ -175,17 +158,17 @@ struct gen_block_miner_tx_has_out_to_alice : public gen_block_accepted_base<2> bool generate(std::vector& events) const; }; -struct gen_block_has_invalid_tx : public gen_block_verification_base<1> +struct gen_block_has_invalid_tx : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_is_too_big : public gen_block_verification_base<1> +struct gen_block_is_too_big : public gen_block_verification_base<2> { bool generate(std::vector& events) const; }; -struct gen_block_wrong_version_agains_hardfork : public gen_block_verification_base<1> +struct gen_block_wrong_version_agains_hardfork : public gen_block_verification_base<2> { public: gen_block_wrong_version_agains_hardfork(); @@ -193,8 +176,6 @@ public: bool generate(std::vector& events) const; }; - - struct gen_block_invalid_binary_format : public test_chain_unit_base { gen_block_invalid_binary_format(); @@ -205,4 +186,4 @@ struct gen_block_invalid_binary_format : public test_chain_unit_base private: size_t m_corrupt_blocks_begin_idx; -}; \ No newline at end of file +}; diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index ce7eb0c8..be5ca06f 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -968,7 +968,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(multisig_and_unlock_time); GENERATE_AND_PLAY(multisig_and_coinbase); GENERATE_AND_PLAY(multisig_with_same_id_in_pool); - GENERATE_AND_PLAY(multisig_and_checkpoints); + GENERATE_AND_PLAY_HF(multisig_and_checkpoints, "0"); // TODO: fix for HF 1-3 (checkpoint hash check) GENERATE_AND_PLAY(multisig_and_checkpoints_bad_txs); GENERATE_AND_PLAY(multisig_and_altchains); GENERATE_AND_PLAY(multisig_out_make_and_spent_in_altchain); @@ -1028,7 +1028,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_checkpoints_pos_validation_on_altchain); GENERATE_AND_PLAY(gen_checkpoints_and_invalid_tx_to_pool); GENERATE_AND_PLAY(gen_checkpoints_set_after_switching_to_altchain); - GENERATE_AND_PLAY(gen_no_attchments_in_coinbase); + GENERATE_AND_PLAY_HF(gen_no_attchments_in_coinbase, "0"); GENERATE_AND_PLAY(gen_no_attchments_in_coinbase_gentime); GENERATE_AND_PLAY(gen_alias_tests); @@ -1039,10 +1039,10 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_alias_update_after_addr_changed); GENERATE_AND_PLAY(gen_alias_blocking_reg_by_invalid_tx); GENERATE_AND_PLAY(gen_alias_blocking_update_by_invalid_tx); - GENERATE_AND_PLAY(gen_alias_reg_with_locked_money); + GENERATE_AND_PLAY_HF(gen_alias_reg_with_locked_money, "*"); GENERATE_AND_PLAY(gen_alias_too_small_reward); GENERATE_AND_PLAY(gen_alias_too_much_reward); - GENERATE_AND_PLAY(gen_alias_tx_no_outs); + GENERATE_AND_PLAY_HF(gen_alias_tx_no_outs, "*"); GENERATE_AND_PLAY(gen_alias_switch_and_check_block_template); GENERATE_AND_PLAY(gen_alias_too_many_regs_in_block_template); GENERATE_AND_PLAY(gen_alias_update_for_free); @@ -1052,7 +1052,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_wallet_refreshing_on_chain_switch); GENERATE_AND_PLAY(gen_wallet_refreshing_on_chain_switch_2); GENERATE_AND_PLAY(gen_wallet_unconfirmed_tx_from_tx_pool); - GENERATE_AND_PLAY(gen_wallet_save_load_and_balance); + GENERATE_AND_PLAY_HF(gen_wallet_save_load_and_balance, "*"); GENERATE_AND_PLAY(gen_wallet_mine_pos_block); GENERATE_AND_PLAY(gen_wallet_unconfirmed_outdated_tx); GENERATE_AND_PLAY(gen_wallet_unlock_by_block_and_by_time); @@ -1139,30 +1139,30 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(random_outs_and_burnt_coins); // 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); disabled becouse impossible to generate text chain with wrong prev_id - pow hash not works without chaining - 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_has_2_in); - GENERATE_AND_PLAY(gen_block_miner_tx_with_txin_to_key); - GENERATE_AND_PLAY(gen_block_miner_tx_out_is_small); - 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); - GENERATE_AND_PLAY(gen_block_wrong_version_agains_hardfork); + GENERATE_AND_PLAY_HF(gen_block_big_major_version, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_big_minor_version, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_ts_not_checked, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_ts_in_past, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_ts_in_future, "0,3"); + //GENERATE_AND_PLAY(gen_block_invalid_prev_id); disabled because impossible to generate text chain with wrong prev_id - pow hash not works without chaining + GENERATE_AND_PLAY_HF(gen_block_invalid_nonce, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_no_miner_tx, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_unlock_time_is_low, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_unlock_time_is_high, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_unlock_time_is_timestamp_in_past, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_unlock_time_is_timestamp_in_future, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_height_is_low, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_height_is_high, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_has_2_tx_gen_in, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_has_2_in, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_with_txin_to_key, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_out_is_small, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_out_is_big, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_has_no_out, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_miner_tx_has_out_to_alice, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_has_invalid_tx, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_is_too_big, "0,3"); + GENERATE_AND_PLAY_HF(gen_block_wrong_version_agains_hardfork, "0,3"); //GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 10 diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index d0f31171..f6169cb4 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -669,11 +669,6 @@ bool gen_checkpoints_pos_validation_on_altchain::init_runtime_config(currency::c gen_no_attchments_in_coinbase::gen_no_attchments_in_coinbase() { - m_hardforks.m_height_the_hardfork_n_active_after[1] = 1440; - m_hardforks.m_height_the_hardfork_n_active_after[2] = 1800; - m_hardforks.m_height_the_hardfork_n_active_after[3] = 1801; - m_hardforks.m_height_the_hardfork_n_active_after[4] = 50000000000; - generator.set_hardforks(m_hardforks); // NOTE: This test is made deterministic to be able to correctly set up checkpoint. random_state_test_restorer::reset_random(); // random generator's state was previously stored, will be restore on dtor (see also m_random_state_test_restorer) @@ -692,6 +687,7 @@ bool gen_no_attchments_in_coinbase::generate(std::vector& even block blk_0 = AUTO_VAL_INIT(blk_0); generator.construct_genesis_block(blk_0, m_miner_acc, ts); events.push_back(blk_0); + DO_CALLBACK(events, "configure_core"); DO_CALLBACK(events, "check_not_being_in_cp_zone"); DO_CALLBACK(events, "init_config_set_cp"); diff --git a/tests/core_tests/multisig_wallet_tests.cpp b/tests/core_tests/multisig_wallet_tests.cpp index 8f7837b3..1253b6ee 100644 --- a/tests/core_tests/multisig_wallet_tests.cpp +++ b/tests/core_tests/multisig_wallet_tests.cpp @@ -1632,10 +1632,6 @@ multisig_and_checkpoints::multisig_and_checkpoints() { // NOTE: This test is made deterministic to be able to correctly set up checkpoint. random_state_test_restorer::reset_random(); // random generator's state was previously stored, will be restore on dtor (see also m_random_state_test_restorer) - m_hardforks.m_height_the_hardfork_n_active_after[1] = 1440; - m_hardforks.m_height_the_hardfork_n_active_after[2] = 1800; - m_hardforks.m_height_the_hardfork_n_active_after[3] = 1801; - m_hardforks.m_height_the_hardfork_n_active_after[4] = 50000000000; REGISTER_CALLBACK_METHOD(multisig_and_checkpoints, set_cp); } @@ -1681,6 +1677,7 @@ bool multisig_and_checkpoints::generate(std::vector& events) c std::vector destinations; MAKE_GENESIS_BLOCK(events, blk_0, preminer_acc, ts); + DO_CALLBACK(events, "configure_core"); // set checkpoint DO_CALLBACK(events, "set_cp"); REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2); From 00c4ac3314e52f632ba6ad064098cea5ebed04e4 Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 5 Jun 2023 20:25:16 +0200 Subject: [PATCH 08/18] coretests: adapted few more tests to new testing environment --- tests/core_tests/chaingen_main.cpp | 6 ++-- tests/core_tests/checkpoints_tests.cpp | 2 +- tests/core_tests/wallet_tests.cpp | 43 ++++++++++---------------- tests/core_tests/wallet_tests.h | 5 +-- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index be5ca06f..067464fc 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1028,7 +1028,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_checkpoints_pos_validation_on_altchain); GENERATE_AND_PLAY(gen_checkpoints_and_invalid_tx_to_pool); GENERATE_AND_PLAY(gen_checkpoints_set_after_switching_to_altchain); - GENERATE_AND_PLAY_HF(gen_no_attchments_in_coinbase, "0"); + GENERATE_AND_PLAY_HF(gen_no_attchments_in_coinbase, "3"); GENERATE_AND_PLAY(gen_no_attchments_in_coinbase_gentime); GENERATE_AND_PLAY(gen_alias_tests); @@ -1053,7 +1053,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_wallet_refreshing_on_chain_switch_2); GENERATE_AND_PLAY(gen_wallet_unconfirmed_tx_from_tx_pool); GENERATE_AND_PLAY_HF(gen_wallet_save_load_and_balance, "*"); - GENERATE_AND_PLAY(gen_wallet_mine_pos_block); + GENERATE_AND_PLAY_HF(gen_wallet_mine_pos_block, "3"); GENERATE_AND_PLAY(gen_wallet_unconfirmed_outdated_tx); GENERATE_AND_PLAY(gen_wallet_unlock_by_block_and_by_time); GENERATE_AND_PLAY(gen_wallet_payment_id); @@ -1076,7 +1076,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(wallet_outputs_with_same_key_image); GENERATE_AND_PLAY(wallet_unconfirmed_tx_expiration); GENERATE_AND_PLAY(wallet_unconfimed_tx_balance); - GENERATE_AND_PLAY(packing_outputs_on_pos_minting_wallet); + GENERATE_AND_PLAY_HF(packing_outputs_on_pos_minting_wallet, "3"); GENERATE_AND_PLAY(wallet_watch_only_and_chain_switch); GENERATE_AND_PLAY(wallet_rpc_integrated_address); diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index f6169cb4..49eeafc2 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -704,7 +704,7 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t crc.pos_minimum_heigh = 1; c.get_blockchain_storage().set_core_runtime_config(crc); - m_checkpoints.add_checkpoint(12, "2a6e13df811eccce121c0de4dbdcc640de1d37c8459c2c8ea02af39717779836"); + m_checkpoints.add_checkpoint(12, "475331fb4a325e722ddbc2d087d32687a58392e5a9314001120de0f2ce7737f2"); c.set_checkpoints(currency::checkpoints(m_checkpoints)); return true; diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index 36738065..a342303b 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -587,7 +587,6 @@ bool gen_wallet_save_load_and_balance::c3_load_refresh_check_balance(currency::c gen_wallet_mine_pos_block::gen_wallet_mine_pos_block() { REGISTER_CALLBACK_METHOD(gen_wallet_mine_pos_block, c1); - REGISTER_CALLBACK_METHOD(gen_wallet_mine_pos_block, set_core_config); } bool gen_wallet_mine_pos_block::generate(std::vector& events) const @@ -607,7 +606,7 @@ bool gen_wallet_mine_pos_block::generate(std::vector& events) generator.construct_genesis_block(blk_0, miner_acc, test_core_time::get_time()); events.push_back(blk_0); - DO_CALLBACK(events, "set_core_config"); + DO_CALLBACK(events, "configure_core"); REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); @@ -620,15 +619,6 @@ bool gen_wallet_mine_pos_block::generate(std::vector& events) return true; } -bool gen_wallet_mine_pos_block::set_core_config(currency::core& c, size_t ev_index, const std::vector& events) -{ - core_runtime_config crc = c.get_blockchain_storage().get_core_runtime_config(); - crc.pos_minimum_heigh = TESTS_POS_CONFIG_POS_MINIMUM_HEIGH; - crc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE; - c.get_blockchain_storage().set_core_runtime_config(crc); - return true; -} - bool gen_wallet_mine_pos_block::c1(currency::core& c, size_t ev_index, const std::vector& events) { std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX); @@ -650,7 +640,7 @@ bool gen_wallet_mine_pos_block::c1(currency::core& c, size_t ev_index, const std bool r = c.get_blockchain_storage().get_top_block(top_block); CHECK_AND_ASSERT_MES(r && is_pos_block(top_block), false, "get_top_block failed or smth goes wrong"); uint64_t top_block_reward = get_outs_money_amount(top_block.miner_tx); - CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0), false, ""); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", top_block_reward, top_block_reward - MK_TEST_COINS(2000), 0, 0, 0), false, ""); alice_wlt->reset_password(g_wallet_password); alice_wlt->store(g_wallet_filename); @@ -3361,8 +3351,8 @@ bool wallet_unconfimed_tx_balance::c1(currency::core& c, size_t ev_index, const packing_outputs_on_pos_minting_wallet::packing_outputs_on_pos_minting_wallet() { REGISTER_CALLBACK_METHOD(packing_outputs_on_pos_minting_wallet, c1); - REGISTER_CALLBACK_METHOD(packing_outputs_on_pos_minting_wallet, set_core_config); } + bool packing_outputs_on_pos_minting_wallet::generate(std::vector& events) const { @@ -3380,9 +3370,19 @@ bool packing_outputs_on_pos_minting_wallet::generate(std::vectorbalance(unlocked, awaiting_in, awaiting_out, mined); + + size_t n_blocks = CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5; + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, n_blocks); + m_mined_amount = n_blocks * COIN; + + REFRESH_TEST_WALLET_AT_GEN_TIME(events, miner_wlt, blk_0r, n_blocks); + CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(miner_wlt, m_premine_amount + m_mined_amount); //MAKE_TX_FEE(events, tx_0, miner_acc, alice_acc, MK_TEST_COINS(2000), TESTS_DEFAULT_FEE, blk_0r); //MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); @@ -3393,15 +3393,6 @@ bool packing_outputs_on_pos_minting_wallet::generate(std::vector& events) -{ - core_runtime_config crc = c.get_blockchain_storage().get_core_runtime_config(); - crc.pos_minimum_heigh = TESTS_POS_CONFIG_POS_MINIMUM_HEIGH; - crc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE; - c.get_blockchain_storage().set_core_runtime_config(crc); - return true; -} - bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_index, const std::vector& events) { std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX); @@ -3412,7 +3403,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5, false, "Incorrect numbers of blocks fetched"); miner_wlt->set_pos_mint_packing_size(4); - CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0), false, ""); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", m_premine_amount + m_mined_amount, uint64_max, uint64_max, 0, 0), false, ""); miner_wlt->try_mint_pos(); @@ -3424,7 +3415,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde bool r = c.get_blockchain_storage().get_top_block(top_block); CHECK_AND_ASSERT_MES(r && is_pos_block(top_block), false, "get_top_block failed or smth goes wrong"); uint64_t top_block_reward = get_outs_money_amount(top_block.miner_tx); - CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0), false, ""); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", m_premine_amount + m_mined_amount + COIN), false, ""); miner_wlt->reset_password(g_wallet_password); miner_wlt->store(g_wallet_filename); diff --git a/tests/core_tests/wallet_tests.h b/tests/core_tests/wallet_tests.h index ac5569d5..46905ead 100644 --- a/tests/core_tests/wallet_tests.h +++ b/tests/core_tests/wallet_tests.h @@ -44,7 +44,6 @@ struct gen_wallet_mine_pos_block : public wallet_test gen_wallet_mine_pos_block(); bool generate(std::vector& events) const; - bool set_core_config(currency::core& c, size_t ev_index, const std::vector& events); bool c1(currency::core& c, size_t ev_index, const std::vector& events); bool c2(currency::core& c, size_t ev_index, const std::vector& events); @@ -256,8 +255,10 @@ struct packing_outputs_on_pos_minting_wallet : public wallet_test { packing_outputs_on_pos_minting_wallet(); bool generate(std::vector& events) const; - bool set_core_config(currency::core& c, size_t ev_index, const std::vector& events); bool c1(currency::core& c, size_t ev_index, const std::vector& events); + + mutable uint64_t m_premine_amount = 0; + mutable uint64_t m_mined_amount = 0; }; struct wallet_sending_to_integrated_address : public wallet_test From ce67a1bd1c2e1d27965e6fc367d2da38d35dd789 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 6 Jun 2023 22:37:32 +0200 Subject: [PATCH 09/18] coretests: fixed several bugs in chaingen (init_test_wallet now sets hardforks correctly, fill_sources_and_destinations has been adjected to correctly set destinations in case of random split policy) --- tests/core_tests/chaingen.cpp | 25 ++++++++++++++++--------- tests/core_tests/chaingen.h | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 6c375181..45b51919 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -965,6 +965,7 @@ bool test_generator::init_test_wallet(const currency::account_base& account, con crc.get_core_time = test_core_time::get_time; crc.pos_minimum_heigh = TESTS_POS_CONFIG_POS_MINIMUM_HEIGH; crc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE; + crc.hard_forks = m_hardforks; std::shared_ptr w(new tools::wallet2); w->set_core_runtime_config(crc); @@ -1460,21 +1461,21 @@ bool fill_tx_sources_and_destinations(const std::vector& event uint64_t inputs_amount = get_inputs_amount(sources); CHECK_AND_ASSERT_MES(inputs_amount >= amount + fee, false, "Pre-condition fail: inputs_amount is less than amount + fee"); - uint64_t cache_back = inputs_amount - (amount + fee); + uint64_t change_amount = inputs_amount - (amount + fee); if (b_multisig) { destinations.push_back(tx_destination_entry(amount, to)); if (minimum_sigs != SIZE_MAX) destinations.back().minimum_sigs = minimum_sigs; // set custom minimum_sigs only if != SIZE_MAX, use default in tx_destination_entry::ctor() otherwise - if (cache_back > 0) - destinations.push_back(tx_destination_entry(cache_back, from.account_address)); + if (change_amount > 0) + destinations.push_back(tx_destination_entry(change_amount, from.account_address)); } else { tx_destination_entry change_dst = AUTO_VAL_INIT(change_dst); - if (cache_back > 0) - change_dst = tx_destination_entry(cache_back, from.account_address); + if (change_amount > 0) + change_dst = tx_destination_entry(change_amount, from.account_address); std::vector dsts(1, tx_destination_entry(amount, to.back())); uint64_t dust = 0; const test_gentime_settings& tgs = test_generator::get_test_gentime_settings(); @@ -1491,13 +1492,19 @@ bool fill_tx_sources_and_destinations(const std::vector& event break; case tests_random_split_strategy: { - size_t outs_count = cache_back > 0 ? 2 : 1; + size_t outs_count = change_amount > 0 ? 2 : 1; if (outs_count < tgs.rss_min_number_of_outputs) { - // decompose both target and cache back amounts + // decompose both target and change amounts // TODO: support tgs.tx_max_out_amount - decompose_amount_randomly(amount, [&](uint64_t a){ destinations.emplace_back(a, to.back()); }, tgs.rss_min_number_of_outputs, tgs.rss_num_digits_to_keep); - decompose_amount_randomly(cache_back, [&](uint64_t a){ destinations.emplace_back(a, from.account_address); }, tgs.rss_min_number_of_outputs, tgs.rss_num_digits_to_keep); + decompose_amount_randomly(amount, [&](uint64_t a){ destinations.emplace_back(a, to.back()); }, tgs.rss_min_number_of_outputs, tgs.rss_num_digits_to_keep); + decompose_amount_randomly(change_amount, [&](uint64_t a){ destinations.emplace_back(a, from.account_address); }, tgs.rss_min_number_of_outputs, tgs.rss_num_digits_to_keep); + } + else + { + CHECK_AND_ASSERT_MES(change_amount > 0, false, "internal error: change_amount is zero"); + destinations = dsts; + destinations.push_back(change_dst); } } break; diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index e59d3e79..936e422a 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -225,7 +225,7 @@ VARIANT_TAG(binary_archive, core_hardforks_config, 0xd2); typedef boost::variant test_event_entry; typedef std::unordered_map map_hash2tx_t; -enum test_tx_split_strategy { tests_void_split_strategy, tests_null_split_strategy, tests_digits_split_strategy, tests_random_split_strategy }; +enum test_tx_split_strategy { tests_default_split_strategy /*height-based, TODO*/, tests_void_split_strategy, tests_null_split_strategy, tests_digits_split_strategy, tests_random_split_strategy }; struct test_gentime_settings { test_tx_split_strategy split_strategy = tests_digits_split_strategy; From a0fb876a48b86a2e6a8cf24378de8b0af7d60dac Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 6 Jun 2023 22:43:09 +0200 Subject: [PATCH 10/18] coretests: added new test assets_and_explicit_native_coins_in_outs, which uncovers a bug in wallet2 where the explicit asset id was incorrectly set when it shouldn't have been --- tests/core_tests/chaingen_main.cpp | 4 +- tests/core_tests/multiassets_test.cpp | 194 ++++++++++++++++++++++++++ tests/core_tests/multiassets_test.h | 12 +- 3 files changed, 208 insertions(+), 2 deletions(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 067464fc..06e89653 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1247,13 +1247,15 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(zarcanum_basic_test); - GENERATE_AND_PLAY(multiassets_basic_test); + GENERATE_AND_PLAY_HF(multiassets_basic_test, "4-*"); GENERATE_AND_PLAY(ionic_swap_basic_test); GENERATE_AND_PLAY(zarcanum_test_n_inputs_validation); GENERATE_AND_PLAY(zarcanum_gen_time_balance); GENERATE_AND_PLAY(zarcanum_txs_with_big_shuffled_decoy_set_shuffled); GENERATE_AND_PLAY(zarcanum_pos_block_math); GENERATE_AND_PLAY(zarcanum_in_alt_chain); + GENERATE_AND_PLAY(assets_and_explicit_native_coins_in_outs); + // GENERATE_AND_PLAY(gen_block_reward); // END OF TESTS */ diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp index b0c2f026..718e5cc4 100644 --- a/tests/core_tests/multiassets_test.cpp +++ b/tests/core_tests/multiassets_test.cpp @@ -141,5 +141,199 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v + return true; +} + +//------------------------------------------------------------------------------ + +assets_and_explicit_native_coins_in_outs::assets_and_explicit_native_coins_in_outs() +{ + REGISTER_CALLBACK_METHOD(assets_and_explicit_native_coins_in_outs, c1_alice_cannot_deploy_asset); + REGISTER_CALLBACK_METHOD(assets_and_explicit_native_coins_in_outs, c2_alice_deploys_asset); + + m_hardforks.clear(); + m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1); +} + +bool assets_and_explicit_native_coins_in_outs::generate(std::vector& events) const +{ + /* Test idea: + * 1) make sure an asset cannot be deployed if there's no ZC outputs available; + * 2) make sure an asset emission transaction has hidden asset ids in all outputs; + * 3) (NOT DONE YET) make sure tx with at least one input with at least one reference to non-explicit native asset id has non-explicit asset ids in outs (TODO: move to separate test) + */ + + bool r = false; + + uint64_t ts = test_core_time::get_time(); + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks + + // HF4 requires tests_random_split_strategy (for 2 outputs minimum) + test_gentime_settings tgts = generator.get_test_gentime_settings(); + tgts.split_strategy = tests_random_split_strategy; + generator.set_test_gentime_settings(tgts); + + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + DO_CALLBACK_PARAMS(events, "check_hardfork_inactive", static_cast(ZANO_HARDFORK_04_ZARCANUM)); + + // tx_0: miner -> Alice + // make tx_0 before HF4, so Alice will have only bare outs + m_alice_initial_balance = MK_TEST_COINS(1000) + TESTS_DEFAULT_FEE; + transaction tx_0{}; + std::vector sources; + std::vector destinations; + r = fill_tx_sources_and_destinations(events, blk_0r, miner_acc, alice_acc, m_alice_initial_balance, TESTS_DEFAULT_FEE, 0, sources, destinations, true /* spends */, false /* unlock time */); + CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources_and_destinations failed"); + r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_0, get_tx_version_from_events(events), 0); + CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + + ADD_CUSTOM_EVENT(events, tx_0); + MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); + + // make sure HF4 has been activated + DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast(ZANO_HARDFORK_04_ZARCANUM)); + + // rewind blocks + REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + // check Alice's balance and make sure she cannot deploy an asset + DO_CALLBACK(events, "c1_alice_cannot_deploy_asset"); + + // tx_1: Alice -> Alice (all coins) : this will convert two Alice's outputs to ZC outs (since we're at post-HF4 zone) + MAKE_TX(events, tx_1, alice_acc, alice_acc, m_alice_initial_balance - TESTS_DEFAULT_FEE, blk_1r); + CHECK_AND_ASSERT_MES(tx_1.vout.size() == 2, false, "unexpected tx_1.vout.size : " << tx_1.vout.size()); + + // make sure that all tx_1 outputs have explicit hative coin asset id + for(auto& out : tx_1.vout) + { + CHECK_AND_ASSERT_MES(out.type() == typeid(tx_out_zarcanum), false, "invalid out type"); + const tx_out_zarcanum& out_zc = boost::get(out); + CHECK_AND_ASSERT_MES(out_zc.blinded_asset_id == native_coin_asset_id_1div8, false, "tx_1 has non-explicit asset id in outputs"); + } + + MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_1); + + // rewind blocks + REWIND_BLOCKS_N_WITH_TIME(events, blk_2r, blk_2, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + // check Alice's balance and make sure she CAN deploy an asset now + DO_CALLBACK(events, "c2_alice_deploys_asset"); + + return true; +} + +bool assets_and_explicit_native_coins_in_outs::c1_alice_cannot_deploy_asset(currency::core& c, size_t ev_index, const std::vector& events) +{ + std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); + alice_wlt->refresh(); + + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", m_alice_initial_balance, 0, m_alice_initial_balance, 0, 0), false, ""); + + asset_descriptor_base adb{}; + adb.total_max_supply = 10; + adb.full_name = "it doesn't matter"; + adb.ticker = "really"; + adb.decimal_point = 12; + + std::vector destinations; + destinations.emplace_back(adb.total_max_supply, m_accounts[MINER_ACC_IDX].get_public_address(), null_pkey); + + transaction asset_emission_tx{}; + crypto::public_key asset_id = null_pkey; + bool r = false; + try + { + alice_wlt->deploy_new_asset(adb, destinations, asset_emission_tx, asset_id); + } + catch(...) + { + r = true; + } + + CHECK_AND_ASSERT_MES(r, false, "Alice successfully deployed an asset, which is unexpected (she has no ZC outs available)"); + + return true; +} + +bool assets_and_explicit_native_coins_in_outs::c2_alice_deploys_asset(currency::core& c, size_t ev_index, const std::vector& events) +{ + bool r = false; + std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); + alice_wlt->refresh(); + + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", m_alice_initial_balance - TESTS_DEFAULT_FEE, 0, m_alice_initial_balance - TESTS_DEFAULT_FEE, 0, 0), false, ""); + + // make sure Alice has two UTXO now + tools::wallet2::transfer_container transfers{}; + alice_wlt->get_transfers(transfers); + size_t unspent_transfers = std::count_if(transfers.begin(), transfers.end(), [](const tools::wallet2::transfer_details& tr){ return !tr.is_spent(); }); + CHECK_AND_ASSERT_MES(unspent_transfers == 2, false, "unexpected number of Alice's unspent transfers: " << unspent_transfers); + + asset_descriptor_base adb{}; + adb.total_max_supply = 100 * 1000000000000; + adb.full_name = "very confidential asset"; + adb.ticker = "VCA"; + adb.decimal_point = 12; + + std::vector destinations; + destinations.emplace_back(adb.total_max_supply / 2, m_accounts[MINER_ACC_IDX].get_public_address(), null_pkey); + destinations.emplace_back(adb.total_max_supply / 2, m_accounts[MINER_ACC_IDX].get_public_address(), null_pkey); + + transaction asset_emission_tx{}; + crypto::public_key asset_id = null_pkey; + + alice_wlt->deploy_new_asset(adb, destinations, asset_emission_tx, asset_id); + + + // make sure the emission tx is correct + CHECK_AND_ASSERT_MES(asset_emission_tx.vout.size() > 2, false, "Unexpected vout size: " << asset_emission_tx.vout.size()); + for(auto& out : asset_emission_tx.vout) + { + CHECK_AND_ASSERT_MES(out.type() == typeid(tx_out_zarcanum), false, "invalid out type"); + const tx_out_zarcanum& out_zc = boost::get(out); + // as soon as this is the asset emmiting transaction, no output has an obvious asset id + // make sure it is so + CHECK_AND_ASSERT_MES(out_zc.blinded_asset_id != native_coin_asset_id_1div8, false, "One of outputs has explicit native asset id, which is unexpected"); + } + + // get this tx confirmed + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + + r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed"); + + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + + // check Alice balance, make sure all native coins are unlocked + alice_wlt->refresh(); + uint64_t alice_balance = m_alice_initial_balance - TESTS_DEFAULT_FEE * 2; + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", alice_balance, 0, alice_balance, 0, 0), false, ""); + + // now Alice only has UTXO with non explicit asset id + // Transfer all of them back to miner and check asset ids of outputs + transaction tx_2{}; + alice_wlt->transfer(alice_balance - TESTS_DEFAULT_FEE, m_accounts[MINER_ACC_IDX].get_public_address(), tx_2, native_coin_asset_id); + + CHECK_AND_ASSERT_MES(tx_2.vout.size() == 2, false, "unexpected tx_2.vout.size : " << tx_2.vout.size()); + for(auto& out : tx_2.vout) + { + CHECK_AND_ASSERT_MES(out.type() == typeid(tx_out_zarcanum), false, "invalid out type"); + const tx_out_zarcanum& out_zc = boost::get(out); + CHECK_AND_ASSERT_MES(out_zc.blinded_asset_id != native_coin_asset_id_1div8, false, "One of outputs has explicit native asset id, which is unexpected"); + } + + // finally, get this tx confirmed + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + + r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed"); + + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + return true; } diff --git a/tests/core_tests/multiassets_test.h b/tests/core_tests/multiassets_test.h index 74e17bf6..fbfeb4b3 100644 --- a/tests/core_tests/multiassets_test.h +++ b/tests/core_tests/multiassets_test.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2023 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -16,3 +16,13 @@ struct multiassets_basic_test : public wallet_test bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; +struct assets_and_explicit_native_coins_in_outs : public wallet_test +{ + assets_and_explicit_native_coins_in_outs(); + bool generate(std::vector& events) const; + bool c1_alice_cannot_deploy_asset(currency::core& c, size_t ev_index, const std::vector& events); + bool c2_alice_deploys_asset(currency::core& c, size_t ev_index, const std::vector& events); + + mutable uint64_t m_alice_initial_balance = 0; +}; + From 9030bfdc2b911008c87e58c63e8761662976b699 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 6 Jun 2023 22:46:37 +0200 Subject: [PATCH 11/18] coretests: minor improvements around multiassets_basic_test --- tests/core_tests/multiassets_test.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp index 718e5cc4..8c31dbb5 100644 --- a/tests/core_tests/multiassets_test.cpp +++ b/tests/core_tests/multiassets_test.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2023 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,15 +9,14 @@ #include "random_helper.h" -#define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE) +using namespace currency; +//------------------------------------------------------------------------------ + +#define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE) #define AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC 500000000000000000 - - -using namespace currency; uint64_t multiassets_basic_test::ts_starter = 0; -//------------------------------------------------------------------------------ multiassets_basic_test::multiassets_basic_test() { // TODO: remove the following line @@ -25,10 +24,7 @@ multiassets_basic_test::multiassets_basic_test() LOG_PRINT_MAGENTA("STARTER TS: " << ts_starter, LOG_LEVEL_0); random_state_test_restorer::reset_random(ts_starter); - REGISTER_CALLBACK_METHOD(multiassets_basic_test, configure_core); REGISTER_CALLBACK_METHOD(multiassets_basic_test, c1); - - m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, 1); } bool multiassets_basic_test::generate(std::vector& events) const @@ -40,7 +36,6 @@ bool multiassets_basic_test::generate(std::vector& events) con uint64_t ts = 145000000; MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks - set_hard_fork_heights_to_generator(generator); //TODO: Need to make sure REWIND_BLOCKS_N and other coretests codebase are capable of following hardfork4 rules //in this test hardfork4 moment moved to runtime section REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); From 3004dbc684704130e61b49c8f87e8899037cfa4c Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 6 Jun 2023 22:54:29 +0200 Subject: [PATCH 12/18] gcc warning fixed --- tests/core_tests/chaingen_helpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core_tests/chaingen_helpers.h b/tests/core_tests/chaingen_helpers.h index a9537274..b95613af 100644 --- a/tests/core_tests/chaingen_helpers.h +++ b/tests/core_tests/chaingen_helpers.h @@ -310,8 +310,8 @@ inline bool put_alias_via_tx_to_list(const currency::hard_forks_descriptor& hf, uint64_t burnt_amount = 0; if (!check_native_coins_amount_burnt_in_outs(tx_set.back(), alias_reward, &burnt_amount)) { - CHECK_AND_ASSERT_MES(false, false, "alias reward was not found, expected: " << print_money_brief(alias_reward) - << "; burnt: " << (tx_set.back().version <= TRANSACTION_VERSION_PRE_HF4 ? print_money_brief(burnt_amount) : "hidden") << "; tx: " << get_transaction_hash(tx_set.back())); + CHECK_AND_ASSERT_MES(false, false, "alias reward was not found, expected: " << currency::print_money_brief(alias_reward) + << "; burnt: " << (tx_set.back().version <= TRANSACTION_VERSION_PRE_HF4 ? currency::print_money_brief(burnt_amount) : "hidden") << "; tx: " << get_transaction_hash(tx_set.back())); } return true; From ea45baa4577ea6d8b5e40ff10c54a979e2d65747 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 7 Jun 2023 00:18:22 +0200 Subject: [PATCH 13/18] fixed a bug in wallet2 where the explicit asset id was incorrectly set when it shouldn't have been --- src/currency_core/currency_format_utils.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 6c55d83a..56ef91cd 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2207,10 +2207,9 @@ namespace currency } if (src_entr.is_native_coin()) - { native_coins_input_sum += src_entr.amount; - } - else + + if (src_entr.is_zc()) { // if at least one decoy output of a ZC input has a non-explicit asset id, then we can't say that all inputs are obviously native coins for(const tx_source_entry::output_entry& oe : in_context.outputs) From e4065e7c52b4e3542dbcf932906f759787535eee Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 7 Jun 2023 00:44:11 +0200 Subject: [PATCH 14/18] version bump: 2.0.0.204 -> 2.0.0.205 --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index b0c0eff8..e85499c3 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 204 +#define PROJECT_VERSION_BUILD_NO 205 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" From 4e4982966b1e4d76f52026bd792ff928625bdb52 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 7 Jun 2023 04:25:01 +0200 Subject: [PATCH 15/18] compilation fix for simplewallet --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index a42a81da..0b0292c3 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2394,7 +2394,7 @@ int main(int argc, char* argv[]) if (command_line::get_arg(vm, arg_generate_new_wallet).size() || command_line::get_arg(vm, arg_generate_new_auditable_wallet).size()) return EXIT_FAILURE; - wal.m_use_assets_whitelisting(true); + wal.set_use_assets_whitelisting(true); if (!offline_mode) wal.refresh(); From 831f17d570251cd63b6d63860b979f4fee27d8af Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 7 Jun 2023 15:44:19 +0200 Subject: [PATCH 16/18] gui updated --- src/gui/qt-daemon/layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index b45d5a82..2750d12c 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit b45d5a82285a8804c859e9d3548fae693716cd6a +Subproject commit 2750d12c11f6063e75f6370a4382db7f0784d624 From 544d8acead607eb9f747aa7cc76fb502d61f383c Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 7 Jun 2023 15:45:08 +0200 Subject: [PATCH 17/18] version bump: 2.0.0.205 -> 2.0.0.206 --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index e85499c3..5e1ef50a 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 205 +#define PROJECT_VERSION_BUILD_NO 206 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" From 6aba2d44b65e04ae3c177cdf8089c001a2f5229b Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 8 Jun 2023 04:18:37 +0200 Subject: [PATCH 18/18] coretests: added new test zarcanum_block_with_txs which uncovers a bug in wallet2 Zarcanum PoS generation when block has non-zero txs --- tests/core_tests/chaingen_main.cpp | 1 + tests/core_tests/zarcanum_test.cpp | 179 +++++++++++++++++++++-------- tests/core_tests/zarcanum_test.h | 9 ++ 3 files changed, 142 insertions(+), 47 deletions(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 06e89653..5d1c1851 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1255,6 +1255,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(zarcanum_pos_block_math); GENERATE_AND_PLAY(zarcanum_in_alt_chain); GENERATE_AND_PLAY(assets_and_explicit_native_coins_in_outs); + GENERATE_AND_PLAY(zarcanum_block_with_txs); // GENERATE_AND_PLAY(gen_block_reward); diff --git a/tests/core_tests/zarcanum_test.cpp b/tests/core_tests/zarcanum_test.cpp index 5ad4afb3..0c7d467d 100644 --- a/tests/core_tests/zarcanum_test.cpp +++ b/tests/core_tests/zarcanum_test.cpp @@ -11,8 +11,6 @@ #include "pos_block_builder.h" -#define AMOUNT_TO_TRANSFER_ZARCANUM_BASIC (TESTS_DEFAULT_FEE*10) - using namespace currency; //------------------------------------------------------------------------------ @@ -56,6 +54,48 @@ bool invalidate_zarcanum_sig(size_t n, zarcanum_sig& sig) return true; } +bool make_next_pos_block(test_generator& generator, std::vector& events, const block& prev_block, const account_base& stake_acc, + uint64_t amount_to_find, size_t nmix, const std::vector& transactions, block& result) +{ + bool r = false; + std::vector sources; + + size_t height = get_block_height(prev_block) + 1; + crypto::hash prev_id = get_block_hash(prev_block); + r = fill_tx_sources(sources, events, prev_block, stake_acc.get_keys(), amount_to_find, nmix, true, true, false); + CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); + CHECK_AND_ASSERT_MES(shuffle_source_entries(sources), false, ""); + auto it = std::max_element(sources.begin(), sources.end(), [&](const tx_source_entry& lhs, const tx_source_entry& rhs){ return lhs.amount < rhs.amount; }); + const tx_source_entry& se = *it; + const tx_source_entry::output_entry& oe = se.outputs[se.real_output]; + + crypto::key_image stake_output_key_image {}; + currency::keypair ephemeral_keys {}; + r = generate_key_image_helper(stake_acc.get_keys(), se.real_out_tx_key, se.real_output_in_tx_index, ephemeral_keys, stake_output_key_image); + CHECK_AND_ASSERT_MES(r, false, "generate_key_image_helper failed"); + uint64_t stake_output_gindex = boost::get(oe.out_reference); + + currency::wide_difficulty_type pos_diff{}; + crypto::hash last_pow_block_hash{}, last_pos_block_kernel_hash{}; + r = generator.get_params_for_next_pos_block(prev_id, pos_diff, last_pow_block_hash, last_pos_block_kernel_hash); + CHECK_AND_ASSERT_MES(r, false, "get_params_for_next_pos_block failed"); + + pos_block_builder pb; + pb.step1_init_header(generator.get_hardforks(), height, prev_id); + pb.step2_set_txs(transactions); + + pb.step3a(pos_diff, last_pow_block_hash, last_pos_block_kernel_hash); + + pb.step3b(se.amount, stake_output_key_image, se.real_out_tx_key, se.real_output_in_tx_index, se.real_out_amount_blinding_mask, stake_acc.get_keys().view_secret_key, + stake_output_gindex, prev_block.timestamp, POS_SCAN_WINDOW, POS_SCAN_STEP); + + pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), stake_acc.get_public_address()); + + pb.step5_sign(se, stake_acc.get_keys()); + result = pb.m_block; + return true; +} + //------------------------------------------------------------------------------ @@ -110,7 +150,7 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool"); //create transfer from pre-zarcanum inputs to post-zarcanum inputs - uint64_t transfer_amount = AMOUNT_TO_TRANSFER_ZARCANUM_BASIC + TESTS_DEFAULT_FEE; + uint64_t transfer_amount = TESTS_DEFAULT_FEE*10 + TESTS_DEFAULT_FEE; const size_t batches_to_Alice_count = 4; for(size_t i = 0; i < batches_to_Alice_count; ++i) { @@ -131,7 +171,7 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", transfer_amount * batches_to_Alice_count, UINT64_MAX, transfer_amount * batches_to_Alice_count), false, ""); //create transfer from post-zarcanum inputs to post-zarcanum inputs with mixins - uint64_t transfer_amount2 = AMOUNT_TO_TRANSFER_ZARCANUM_BASIC; + uint64_t transfer_amount2 = TESTS_DEFAULT_FEE*10; size_t nmix = 10; alice_wlt->transfer(transfer_amount2, nmix, m_accounts[BOB_ACC_IDX].get_public_address()); LOG_PRINT_MAGENTA("Zarcanum-2-zarcanum transaction sent from Alice to Bob " << print_money_brief(transfer_amount2), LOG_LEVEL_0); @@ -380,48 +420,6 @@ zarcanum_pos_block_math::zarcanum_pos_block_math() m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, 0); } -bool make_next_pos_block(test_generator& generator, std::vector& events, const block& prev_block, const account_base& stake_acc, - uint64_t amount_to_find, size_t nmix, block& result) -{ - bool r = false; - std::vector sources; - - size_t height = get_block_height(prev_block) + 1; - crypto::hash prev_id = get_block_hash(prev_block); - r = fill_tx_sources(sources, events, prev_block, stake_acc.get_keys(), amount_to_find, nmix, true, true, false); - CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); - CHECK_AND_ASSERT_MES(shuffle_source_entries(sources), false, ""); - auto it = std::max_element(sources.begin(), sources.end(), [&](const tx_source_entry& lhs, const tx_source_entry& rhs){ return lhs.amount < rhs.amount; }); - const tx_source_entry& se = *it; - const tx_source_entry::output_entry& oe = se.outputs[se.real_output]; - - crypto::key_image stake_output_key_image {}; - currency::keypair ephemeral_keys {}; - r = generate_key_image_helper(stake_acc.get_keys(), se.real_out_tx_key, se.real_output_in_tx_index, ephemeral_keys, stake_output_key_image); - CHECK_AND_ASSERT_MES(r, false, "generate_key_image_helper failed"); - uint64_t stake_output_gindex = boost::get(oe.out_reference); - - currency::wide_difficulty_type pos_diff{}; - crypto::hash last_pow_block_hash{}, last_pos_block_kernel_hash{}; - r = generator.get_params_for_next_pos_block(prev_id, pos_diff, last_pow_block_hash, last_pos_block_kernel_hash); - CHECK_AND_ASSERT_MES(r, false, "get_params_for_next_pos_block failed"); - - pos_block_builder pb; - pb.step1_init_header(generator.get_hardforks(), height, prev_id); - pb.step2_set_txs(std::vector()); - - pb.step3a(pos_diff, last_pow_block_hash, last_pos_block_kernel_hash); - - pb.step3b(se.amount, stake_output_key_image, se.real_out_tx_key, se.real_output_in_tx_index, se.real_out_amount_blinding_mask, stake_acc.get_keys().view_secret_key, - stake_output_gindex, prev_block.timestamp, POS_SCAN_WINDOW, POS_SCAN_STEP); - - pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), stake_acc.get_public_address()); - - pb.step5_sign(se, stake_acc.get_keys()); - result = pb.m_block; - return true; -} - bool zarcanum_pos_block_math::generate(std::vector& events) const { bool r = false; @@ -439,7 +437,7 @@ bool zarcanum_pos_block_math::generate(std::vector& events) co for(size_t i = 1; ; ++i) { block blk_1_pos_bad; - CHECK_AND_ASSERT_MES(make_next_pos_block(generator, events, blk_1r, miner_acc, COIN, 10, blk_1_pos_bad), false, ""); + CHECK_AND_ASSERT_MES(make_next_pos_block(generator, events, blk_1r, miner_acc, COIN, 10, std::vector(), blk_1_pos_bad), false, ""); LOG_PRINT_CYAN("i = " << i, LOG_LEVEL_0); if (!invalidate_zarcanum_sig(i, boost::get(blk_1_pos_bad.miner_tx.signatures[0]))) break; @@ -734,3 +732,90 @@ bool zarcanum_in_alt_chain::c1(currency::core& c, size_t ev_index, const std::ve return true; } +//------------------------------------------------------------------------------ + +zarcanum_block_with_txs::zarcanum_block_with_txs() +{ + REGISTER_CALLBACK_METHOD(zarcanum_block_with_txs, c1); + m_hardforks.set_hardfork_height(ZANO_HARDFORK_03, 0); + m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, 23); +} + +bool zarcanum_block_with_txs::generate(std::vector& events) const +{ + // Test idea: make sure Zarcanum PoS block can have txs and the sum of fees is correctly added to the block reward + + bool r = false; + + uint64_t ts = test_core_time::get_time(); + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts); + account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + // + // before HF4 + // + DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast(ZANO_HARDFORK_03)); + DO_CALLBACK_PARAMS(events, "check_hardfork_inactive", static_cast(ZANO_HARDFORK_04_ZARCANUM)); + + // transfer few coins to Alice (one UTXO) + m_alice_balance = MK_TEST_COINS(100); + MAKE_TX(events, tx_0, miner_acc, alice_acc, m_alice_balance, blk_0r); + MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); + + // rewind blocks and make sure Alice has received the coins + REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, m_alice_balance, m_alice_balance, 0, 0, 0)); + + // then miner sends few coins to Bob via a tx with a big fee amount + std::list alice_stake_sources({ alice_acc }); + uint64_t fee = MK_TEST_COINS(123); + MAKE_TX_FEE(events, tx_1, miner_acc, bob_acc, MK_TEST_COINS(1000), fee, blk_1r); + + // and Alice mines a PoS block with this tx -- so Alice is expected to receive the fee + MAKE_NEXT_POS_BLOCK_TX1(events, blk_2, blk_1r, alice_acc, alice_stake_sources, tx_1); + + // make sure Alice received both block reward and the fee + uint64_t mined_amount = COIN + fee; + DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, m_alice_balance + mined_amount, 0, mined_amount, 0, 0)); + m_alice_balance += mined_amount; + + // + // after HF4 + // + MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc); + DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast(ZANO_HARDFORK_04_ZARCANUM)); + + MAKE_TX(events, tx_2, miner_acc, alice_acc, MK_TEST_COINS(200), blk_3); + MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner_acc, tx_2); + m_alice_balance += MK_TEST_COINS(200); + + REWIND_BLOCKS_N_WITH_TIME(events, blk_4r, blk_4, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, m_alice_balance, m_alice_balance, mined_amount, 0, 0)); + + // then miner sends few coins to Bob via a tx with a big fee amount + fee = MK_TEST_COINS(456); + MAKE_TX_FEE(events, tx_3, miner_acc, bob_acc, MK_TEST_COINS(1000), fee, blk_4r); + + // and Alice mines a PoS block with this tx -- so Alice is expected to receive the fee + MAKE_NEXT_POS_BLOCK_TX1(events, blk_5, blk_4r, alice_acc, alice_stake_sources, tx_3); + + // make sure Alice received both block reward and the fee + uint64_t mined_amount_2 = COIN + fee; + DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, m_alice_balance + mined_amount_2, 0, mined_amount + mined_amount_2, 0, 0)); + m_alice_balance += mined_amount_2; + + + + return true; +} + +bool zarcanum_block_with_txs::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + return true; +} diff --git a/tests/core_tests/zarcanum_test.h b/tests/core_tests/zarcanum_test.h index 4afa4eea..36836c8c 100644 --- a/tests/core_tests/zarcanum_test.h +++ b/tests/core_tests/zarcanum_test.h @@ -44,3 +44,12 @@ struct zarcanum_in_alt_chain : public wallet_test bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; +struct zarcanum_block_with_txs : public wallet_test +{ + zarcanum_block_with_txs(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + + mutable uint64_t m_alice_balance = 0; +}; +