diff --git a/src/currency_core/checkpoints.cpp b/src/currency_core/checkpoints.cpp index 2d997691..3dacc47e 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.end()) + 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/tests/unit_tests/check_points_test.cpp b/tests/unit_tests/check_points_test.cpp index 543e2ac6..0c9e5c26 100644 --- a/tests/unit_tests/check_points_test.cpp +++ b/tests/unit_tests/check_points_test.cpp @@ -39,3 +39,48 @@ 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) +{ + 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)); +}