diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 54813472..6bb47719 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -578,13 +578,13 @@ bool blockchain_storage::set_checkpoints(checkpoints&& chk_pts) catch (const std::exception& ex) { m_db.abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK: " << ex.what()); + LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS: " << ex.what()); return false; } catch (...) { m_db.abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK."); + LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS."); return false; } @@ -594,7 +594,7 @@ bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height, { CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() " << m_db_blocks.size()); + CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() = " << m_db_blocks.size()); auto vptr = m_db_blocks[height]; CHECK_AND_ASSERT_MES(vptr.get(), false, "Failed to get block on height"); @@ -626,22 +626,20 @@ bool blockchain_storage::prune_ring_signatures_and_attachments_if_need() { CRITICAL_REGION_LOCAL(m_read_lock); - if (m_db_blocks.size() > 1 && m_checkpoints.get_top_checkpoint_height() && m_checkpoints.get_top_checkpoint_height() > m_db_current_pruned_rs_height) - { - uint64_t pruning_last_height = std::min(m_db_blocks.size() - 1, m_checkpoints.get_top_checkpoint_height()); - if (pruning_last_height > m_db_current_pruned_rs_height) + uint64_t top_block_height = get_top_block_height(); + uint64_t pruning_end_height = m_checkpoints.get_checkpoint_before_height(top_block_height); + if (pruning_end_height > m_db_current_pruned_rs_height) + { + LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_end_height + << " (" << pruning_end_height - m_db_current_pruned_rs_height << " blocks), top block height is " << top_block_height, LOG_LEVEL_0); + uint64_t tx_count = 0, sig_count = 0, attach_count = 0; + for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_end_height; height++) { - LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_last_height - << " (" << pruning_last_height - m_db_current_pruned_rs_height << " blocks)", LOG_LEVEL_0); - uint64_t tx_count = 0, sig_count = 0, attach_count = 0; - for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_last_height; height++) - { - bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count); - CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height); - } - m_db_current_pruned_rs_height = pruning_last_height; - LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0); + bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count); + CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height); } + m_db_current_pruned_rs_height = pruning_end_height; + LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0); } return true; } @@ -1036,7 +1034,9 @@ void blockchain_storage::purge_alt_block_txs_hashs(const block& b) //------------------------------------------------------------------ void blockchain_storage::do_erase_altblock(alt_chain_container::iterator it) { - purge_altblock_keyimages_from_big_heap(it->second.bl, get_block_hash(it->second.bl)); + crypto::hash id = get_block_hash(it->second.bl); + LOG_PRINT_L1("erasing alt block " << print16(id) << " @ " << get_block_height(it->second.bl)); + purge_altblock_keyimages_from_big_heap(it->second.bl, id); purge_alt_block_txs_hashs(it->second.bl); m_alternative_chains.erase(it); } diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 7cb02c41..cad2ca91 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -396,7 +396,7 @@ namespace currency else { CHECK_AND_ASSERT_MES(*block_ind_ptr < m_db_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id) - << " have index record with offset=" << *block_ind_ptr << ", bigger then m_blocks.size()=" << m_db_blocks.size()); + << " have index record with offset=" << *block_ind_ptr << ", bigger then m_db_blocks.size()=" << m_db_blocks.size()); blocks.push_back(m_db_blocks[*block_ind_ptr]->bl); } } diff --git a/src/currency_core/checkpoints.cpp b/src/currency_core/checkpoints.cpp index 2d997691..bbce9815 100644 --- a/src/currency_core/checkpoints.cpp +++ b/src/currency_core/checkpoints.cpp @@ -36,11 +36,11 @@ namespace currency if(height > blockchain_last_block_height) return false; - auto it = m_points.lower_bound(height); + auto it = m_points.lower_bound(height); // if found, it->first >= height if(it == m_points.end()) return false; if(it->first <= blockchain_last_block_height) - return true; + return true; // this is the case only if height <= it->first <= blockchain_last_block_height else return false; } @@ -68,4 +68,27 @@ namespace currency return false; } } + //--------------------------------------------------------------------------- + uint64_t checkpoints::get_checkpoint_before_height(uint64_t height) const + { + // returns height of the leftmost CP with height that is LESS than the given height + // ex: + // If there are two CP at 11 and 15: + // get_checkpoint_before_height(10) = 0 + // get_checkpoint_before_height(11) = 0 + // get_checkpoint_before_height(12) = 11 + // get_checkpoint_before_height(13) = 11 + // get_checkpoint_before_height(14) = 11 + // get_checkpoint_before_height(15) = 11 + // get_checkpoint_before_height(16) = 15 + + uint64_t top_cp = get_top_checkpoint_height(); + if (height > top_cp) + return top_cp; + + auto it = m_points.lower_bound(height); // if found, it->first >= height + if (it == m_points.end() || it == m_points.begin()) + return 0; + return (--it)->first; + } } diff --git a/src/currency_core/checkpoints.h b/src/currency_core/checkpoints.h index a845e6eb..76675e67 100644 --- a/src/currency_core/checkpoints.h +++ b/src/currency_core/checkpoints.h @@ -20,6 +20,8 @@ namespace currency bool is_height_passed_zone(uint64_t height, uint64_t blockchain_last_block_height) const; bool check_block(uint64_t height, const crypto::hash& h) const; uint64_t get_top_checkpoint_height() const; + + uint64_t get_checkpoint_before_height(uint64_t height) const; private: std::map m_points; }; diff --git a/src/gui/qt-daemon/application/mainwindow.cpp b/src/gui/qt-daemon/application/mainwindow.cpp index acdaef1c..083c2afd 100644 --- a/src/gui/qt-daemon/application/mainwindow.cpp +++ b/src/gui/qt-daemon/application/mainwindow.cpp @@ -548,15 +548,29 @@ void MainWindow::restore_pos(bool consider_showed) } else { - - QPoint pos; - QSize sz; - pos.setX(m_config.m_window_position.first); - pos.setY(m_config.m_window_position.second); - sz.setHeight(m_config.m_window_size.first); - sz.setWidth(m_config.m_window_size.second); - this->move(pos); - this->resize(sz); + QPoint point = QApplication::desktop()->screenGeometry().bottomRight(); + if (m_config.m_window_position.first + m_config.m_window_size.second > point.x() || + m_config.m_window_position.second + m_config.m_window_size.first > point.y() + ) + { + QSize sz = AUTO_VAL_INIT(sz); + sz.setHeight(770); + sz.setWidth(1200); + this->resize(sz); + store_window_pos(); + //reset position(screen changed or other reason) + } + else + { + QPoint pos = AUTO_VAL_INIT(pos); + QSize sz = AUTO_VAL_INIT(sz); + pos.setX(m_config.m_window_position.first); + pos.setY(m_config.m_window_position.second); + sz.setHeight(m_config.m_window_size.first); + sz.setWidth(m_config.m_window_size.second); + this->move(pos); + this->resize(sz); + } } if (consider_showed) @@ -645,7 +659,7 @@ bool MainWindow::show_inital() { m_config = AUTO_VAL_INIT(m_config); this->show(); - QSize sz; + QSize sz = AUTO_VAL_INIT(sz); sz.setHeight(770); sz.setWidth(1200); this->resize(sz); diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index 6299e301..20f9219e 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit 6299e3014aea2f1c5055405f37f0e9de4afc60dd +Subproject commit 20f9219e5f782e019983680791a59b79701e0081 diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index b50044b6..3e9cbc80 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -57,7 +57,7 @@ bool clean_data_directory() { std::string config_folder = command_line::get_arg(g_vm, command_line::arg_data_dir); - static const std::set files = { CURRENCY_POOLDATA_FOLDERNAME_OLD, CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD, P2P_NET_DATA_FILENAME, MINER_CONFIG_FILENAME, GUI_SECURE_CONFIG_FILENAME, GUI_CONFIG_FILENAME, GUI_INTERNAL_CONFIG }; + static const std::set files = { CURRENCY_POOLDATA_FOLDERNAME_OLD, CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD, P2P_NET_DATA_FILENAME, MINER_CONFIG_FILENAME, GUI_SECURE_CONFIG_FILENAME, GUI_CONFIG_FILENAME, GUI_INTERNAL_CONFIG2 }; static const std::set prefixes = { CURRENCY_POOLDATA_FOLDERNAME_PREFIX, CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX }; std::vector entries_to_remove; @@ -743,6 +743,9 @@ int main(int argc, char* argv[]) #undef MARK_TEST_AS_POSTPONED + + // TODO // GENERATE_AND_PLAY(wallet_spend_form_auditable_and_track); + GENERATE_AND_PLAY(pos_minting_tx_packing); GENERATE_AND_PLAY(multisig_wallet_test); @@ -814,6 +817,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_checkpoints_reorganize); 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(gen_no_attchments_in_coinbase_gentime); diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index da68a5fd..254a05e6 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -36,13 +36,18 @@ bool checkpoints_test::set_checkpoint(currency::core& c, size_t ev_index, const { if (pcp.hash != null_hash && pcp.hash != get_block_hash(b)) continue; - currency::checkpoints cp; - cp.add_checkpoint(currency::get_block_height(b), epee::string_tools::pod_to_hex(currency::get_block_hash(b))); - c.set_checkpoints(std::move(cp)); + m_local_checkpoints.add_checkpoint(pcp.height, epee::string_tools::pod_to_hex(currency::get_block_hash(b))); + c.set_checkpoints(currency::checkpoints(m_local_checkpoints)); + LOG_PRINT_YELLOW("CHECKPOINT set at height " << pcp.height, LOG_LEVEL_0); + + //for(uint64_t h = 0; h <= pcp.height + 1; ++h) + // LOG_PRINT_MAGENTA("%% " << h << " : " << m_local_checkpoints.get_checkpoint_before_height(h), LOG_LEVEL_0); return true; } } + LOG_ERROR("set_checkpoint failed trying to set checkpoint at height " << pcp.height); + return false; } @@ -395,8 +400,13 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::generate(std::vector attach; + attach.push_back(tx_comment{"jokes are funny"}); + + // tx pool won't accept the tx, because it cannot be verified in CP zone + // set kept_by_block flag, so tx_0 be accepted + events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); + MAKE_TX_ATTACH(events, tx_0, miner_acc, alice, MK_TEST_COINS(1), blk_0r, attach); events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false)); MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); @@ -407,11 +417,12 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::generate(std::vector& events) const +{ + // Test outline: + // 0) no checkpoints are set; + // 1) core is in a subchain, that will become alternative; + // 2) checkpoint is set (in the furute), transaction pruning is executed; + // 3) core continues to sync, chain switching occurs + // Make sure that chain switching is still possible after pruning. + + // 0 ... N N+1 N+2 N+3 N+4 N+5 N+6 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW) + // tx1 + // (0 )- (0r)- (1 )- (2a)- (3a)- <- alt chain + // \ + // \- (2 )- <- main chain + + bool r = false; + GENERATE_ACCOUNT(miner_acc); + GENERATE_ACCOUNT(alice_acc); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + + REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + DO_CALLBACK(events, "check_not_being_in_cp_zone"); + + MAKE_NEXT_BLOCK(events, blk_1, blk_0r, miner_acc); + MAKE_TX(events, tx1, miner_acc, alice_acc, MK_TEST_COINS(1), blk_1); + MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1, miner_acc, tx1); + MAKE_NEXT_BLOCK(events, blk_3a, blk_2a, miner_acc); + + DO_CALLBACK(events, "check_not_being_in_cp_zone"); + + // 0 ... N N+1 N+2 N+3 N+4 N+5 N+6 <- height (N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW) + // +-----------> CP <- checkpoint + // tx1 | + // (0 )- (0r)- (1 )- (2a)- (3a)- <- alt chain + // \ | <- when CP set up + // \- (2 )- (3 )- (4 )- (5 )- (6 )- <- main chain + + DO_CALLBACK_PARAMS(events, "set_checkpoint", params_checkpoint(CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5)); + + MAKE_NEXT_BLOCK(events, blk_2, blk_1, miner_acc); + MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc); + MAKE_NEXT_BLOCK(events, blk_4, blk_3, miner_acc); // <-- this should trigger the switching + + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_4), get_block_hash(blk_4))); + DO_CALLBACK(events, "check_being_in_cp_zone"); + + MAKE_NEXT_BLOCK(events, blk_5, blk_4, miner_acc); // <-- CHECKPOINT + MAKE_NEXT_BLOCK(events, blk_6, blk_5, miner_acc); + + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_6), get_block_hash(blk_6))); + DO_CALLBACK(events, "check_not_being_in_cp_zone"); + + return true; +} diff --git a/tests/core_tests/checkpoints_tests.h b/tests/core_tests/checkpoints_tests.h index 67f84a12..672d9b42 100644 --- a/tests/core_tests/checkpoints_tests.h +++ b/tests/core_tests/checkpoints_tests.h @@ -23,6 +23,9 @@ protected: uint64_t height; crypto::hash hash; }; + +private: + currency::checkpoints m_local_checkpoints; }; struct gen_checkpoints_attachments_basic : public checkpoints_test @@ -109,3 +112,9 @@ struct gen_checkpoints_and_invalid_tx_to_pool : public checkpoints_test bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; + +struct gen_checkpoints_set_after_switching_to_altchain : public checkpoints_test +{ + gen_checkpoints_set_after_switching_to_altchain(); + bool generate(std::vector& events) const; +}; diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index ab62563f..f4f2e027 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -3553,5 +3553,87 @@ bool wallet_watch_only_and_chain_switch::c1(currency::core& c, size_t ev_index, CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, MK_TEST_COINS(7), false, UINT64_MAX, 0, 0, MK_TEST_COINS(7), 0), false, ""); + return true; +} + +//------------------------------------------------------------------------------ + +wallet_spend_form_auditable_and_track::wallet_spend_form_auditable_and_track() +{ + REGISTER_CALLBACK_METHOD(wallet_spend_form_auditable_and_track, c1); +} + +bool wallet_spend_form_auditable_and_track::generate(std::vector& events) const +{ + bool r = false; + + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(true); // Alice has auditable wallet + account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc = alice_acc; bob_acc.make_account_watch_only(); // Bob has Alice's tracking wallet + + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + MAKE_TX(events, tx_1, miner_acc, alice_acc, MK_TEST_COINS(5), blk_0r); + + MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_1); + REWIND_BLOCKS_N(events, blk_1r, blk_1, miner_acc, WALLET_DEFAULT_TX_SPENDABLE_AGE); + + std::vector attachments; + tx_comment comment_attachment = AUTO_VAL_INIT(comment_attachment); + m_comment = "Jokes are funny!"; + comment_attachment.comment = m_comment; + attachments.push_back(comment_attachment); + MAKE_TX_ATTACH(events, tx_2, alice_acc, miner_acc, MK_TEST_COINS(1), blk_1r, attachments); + + MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_2); + + DO_CALLBACK(events, "c1"); + + return true; +} + +bool wallet_spend_form_auditable_and_track::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + bool r = false; + std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX); + std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX); + std::shared_ptr bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX); + + // make sure Alice's wallet is autibale and not watch-only + CHECK_AND_ASSERT_MES(!alice_wlt->is_watch_only() && alice_wlt->is_auditable(), false, "incorrect type of Alice's wallet"); + // make sure Bob's wallet is a tracking wallet + CHECK_AND_ASSERT_MES(bob_wlt->is_watch_only() && bob_wlt->is_auditable(), false, "incorrect type of Bob's wallet"); + + const account_public_address& bob_addr = bob_wlt->get_account().get_public_address(); + const account_public_address& alice_addr = alice_wlt->get_account().get_public_address(); + + // make sure their addresses are linked indeed + CHECK_AND_ASSERT_MES(bob_addr.view_public_key == alice_addr.view_public_key && bob_addr.spend_public_key == alice_addr.spend_public_key, false, + "Bob's tracking wallet address is not linked with Alice's one"); + + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); + + bob_wlt->refresh(); + + // check the balances + CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(3), false, UINT64_MAX, 0, 0, 0, 0), false, ""); + CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, MK_TEST_COINS(3), false, UINT64_MAX, 0, 0, 0, 0), false, ""); + + r = false; + bool r_comment = false; + bob_wlt->enumerate_transfers_history([&](const tools::wallet_public::wallet_transfer_info& wti) { + if (wti.amount == MK_TEST_COINS(5)) + { + r_comment = (wti.comment == m_comment); + if (!r_comment) + return false; // stop + } + return true; // continue + }, true); + CHECK_AND_ASSERT_MES(r, false, "cannot get comment from tx"); + CHECK_AND_ASSERT_MES(r_comment, false, "wrong comment got from tx"); + return true; } diff --git a/tests/core_tests/wallet_tests.h b/tests/core_tests/wallet_tests.h index 17c83bcd..eb54960b 100644 --- a/tests/core_tests/wallet_tests.h +++ b/tests/core_tests/wallet_tests.h @@ -276,3 +276,12 @@ struct wallet_watch_only_and_chain_switch : public wallet_test mutable crypto::hash m_split_point_block_id; mutable uint64_t m_split_point_block_height; }; + +struct wallet_spend_form_auditable_and_track : public wallet_test +{ + wallet_spend_form_auditable_and_track(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + + mutable std::string m_comment; +}; diff --git a/tests/unit_tests/check_points_test.cpp b/tests/unit_tests/check_points_test.cpp index 543e2ac6..ab2372c1 100644 --- a/tests/unit_tests/check_points_test.cpp +++ b/tests/unit_tests/check_points_test.cpp @@ -39,3 +39,87 @@ TEST(checkpoints_test, test_checkpoints_for_alternative) r = cp.is_height_passed_zone(11, 12); ASSERT_FALSE(r); } + + +TEST(checkpoints_test, get_checkpoint_before_height_1) +{ + currency::checkpoints cp; + cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000"); + + for (uint64_t h = 0; h <= 15; ++h) + ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 0); + + ASSERT_TRUE(cp.get_checkpoint_before_height(16) == 15); + + for (uint64_t h = 17; h < 100; ++h) + ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 15); +} + + +TEST(checkpoints_test, get_checkpoint_before_height_2) +{ + currency::checkpoints cp; + cp.add_checkpoint(11, "0000000000000000000000000000000000000000000000000000000000000000"); + cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000"); + + for (uint64_t h = 0; h < 11; ++h) + ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 0); + + ASSERT_TRUE(cp.get_checkpoint_before_height(11) == 0); + + ASSERT_TRUE(cp.get_checkpoint_before_height(12) == 11); + ASSERT_TRUE(cp.get_checkpoint_before_height(13) == 11); + ASSERT_TRUE(cp.get_checkpoint_before_height(14) == 11); + ASSERT_TRUE(cp.get_checkpoint_before_height(15) == 11); + + ASSERT_TRUE(cp.get_checkpoint_before_height(16) == 15); + + for (uint64_t h = 17; h < 100; ++h) + ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 15); +} + + +TEST(checkpoints_test, get_checkpoint_before_height_3) +{ + currency::checkpoints cp; + cp.add_checkpoint(11, "0000000000000000000000000000000000000000000000000000000000000000"); + cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000"); + cp.add_checkpoint(21, "0000000000000000000000000000000000000000000000000000000000000000"); + + for (uint64_t h = 0; h < 11; ++h) + ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 0); + + ASSERT_TRUE(cp.get_checkpoint_before_height(11) == 0); + + ASSERT_TRUE(cp.get_checkpoint_before_height(12) == 11); + ASSERT_TRUE(cp.get_checkpoint_before_height(13) == 11); + ASSERT_TRUE(cp.get_checkpoint_before_height(14) == 11); + ASSERT_TRUE(cp.get_checkpoint_before_height(15) == 11); + + ASSERT_TRUE(cp.get_checkpoint_before_height(16) == 15); + ASSERT_TRUE(cp.get_checkpoint_before_height(17) == 15); + ASSERT_TRUE(cp.get_checkpoint_before_height(18) == 15); + ASSERT_TRUE(cp.get_checkpoint_before_height(19) == 15); + ASSERT_TRUE(cp.get_checkpoint_before_height(20) == 15); + ASSERT_TRUE(cp.get_checkpoint_before_height(21) == 15); + + ASSERT_TRUE(cp.get_checkpoint_before_height(22) == 21); + + for (uint64_t h = 22; h < 100; ++h) + ASSERT_TRUE(cp.get_checkpoint_before_height(h) == 21); +} + + +TEST(checkpoints_test, is_in_checkpoint_zone) +{ + currency::checkpoints cp; + cp.add_checkpoint(11, "0000000000000000000000000000000000000000000000000000000000000000"); + cp.add_checkpoint(15, "0000000000000000000000000000000000000000000000000000000000000000"); + cp.add_checkpoint(21, "0000000000000000000000000000000000000000000000000000000000000000"); + + for (uint64_t h = 0; h < 22; ++h) + ASSERT_TRUE(cp.is_in_checkpoint_zone(h)); + + for (uint64_t h = 22; h < 100; ++h) + ASSERT_FALSE(cp.is_in_checkpoint_zone(h)); +}