From cda2dda44f0f7d9daf8d5340de0e5ab61adde22f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 15 Jul 2019 20:10:50 +0200 Subject: [PATCH] implemented comparing function fo altchains --- contrib/epee/include/misc_log_ex.h | 1 - src/currency_core/blockchain_storage.cpp | 81 ++++++++++++++++++-- src/currency_core/blockchain_storage.h | 3 +- src/currency_core/blockchain_storage_basic.h | 1 + src/currency_core/currency_format_utils.cpp | 11 ++- src/currency_core/currency_format_utils.h | 13 +++- 6 files changed, 94 insertions(+), 16 deletions(-) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 6cc40d13..594f2519 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -263,7 +263,6 @@ DISABLE_VS_WARNINGS(4100) { \ LOG_ERROR("Exception at [" << LOCATION_SS << "], generic unknown exception \"...\""); \ throw std::runtime_error("[EXCEPTION FORWARDED]"); \ - custom_code; \ } diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index cae166cf..a87a9eed 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -116,7 +116,9 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(std::share m_current_fee_median(0), m_current_fee_median_effective_index(0), m_is_reorganize_in_process(false), - m_deinit_is_done(false) + m_deinit_is_done(false), + m_cached_next_pow_difficulty(0), + m_cached_next_pos_difficulty(0) { @@ -1505,7 +1507,6 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: CHECK_AND_ASSERT_MES_CUSTOM(!(pos_block && abei.height < m_core_runtime_config.pos_minimum_heigh), false, bvc.m_verification_failed = true, "PoS block is not allowed on this height"); - //wide_difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei, pos_block); wide_difficulty_type current_diff = get_next_diff_conditional2(pos_block, alt_chain, connection_height); CHECK_AND_ASSERT_MES_CUSTOM(current_diff, false, bvc.m_verification_failed = true, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); @@ -1651,13 +1652,37 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: CATCH_ENTRY_CUSTOM("blockchain_storage::handle_alternative_block", bvc.m_verification_failed = true, false); } //------------------------------------------------------------------ +wide_difficulty_type blockchain_storage::get_x_difficulty_after_height(uint64_t height, bool is_pos) +{ + CRITICAL_REGION_LOCAL(m_read_lock); + CHECK_AND_ASSERT_THROW_MES(height < m_db_blocks.size(), "Internal error: condition failed: height (" << height << ") < m_db_blocks.size() " << m_db_blocks.size()); + wide_difficulty_type diff = 0; + for (uint64_t i = height + 1; i != m_db_blocks.size(); i++) + { + auto bei_ptr = m_db_blocks[i]; + if (is_pos_block(bei_ptr->bl) == is_pos) + { + diff = bei_ptr->difficulty; + break; + } + } + if (diff == 0) + { + //never met x type of block, that meanst that difficulty is current + diff = get_cached_next_difficulty(is_pos); + } + return diff; +} +//------------------------------------------------------------------ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt) { //alt_chain - back is latest(top), first - connection with main chain const block_extended_info& alt_chain_bei = alt_chain.back()->second; + const block_extended_info& connection_point = alt_chain.front()->second; - if (alt_chain_bei.bl.major_version == BLOCK_MAJOR_VERSION_INITAL) + if (alt_chain_bei.bl.major_version == BLOCK_MAJOR_VERSION_INITAL || connection_point.height <= ZANO_HARDFORK_1_AFTER_HEIGHT) { + //use pre-hard fork, old-style comparing if (main_chain_bei.cumulative_diff_adjusted < alt_chain_bei.cumulative_diff_adjusted) return true; else if (main_chain_bei.cumulative_diff_adjusted > alt_chain_bei.cumulative_diff_adjusted) @@ -1678,9 +1703,53 @@ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_ } else if (alt_chain_bei.bl.major_version == CURRENT_BLOCK_MAJOR_VERSION) { - //figure out connection point - const block_extended_info& connection_point = alt_chain.front()->second; + //new rules, applied after HARD_FORK_1 + //to learn this algo please read https://github.com/hyle-team/docs/blob/master/zano/PoS_Analysis_and_improvements_proposal.pdf + wide_difficulty_type difficulty_pos_at_split_point = get_x_difficulty_after_height(connection_point.height - 1, true); + wide_difficulty_type difficulty_pow_at_split_point = get_x_difficulty_after_height(connection_point.height - 1, false); + + difficulties main_cumul_diff = AUTO_VAL_INIT(main_cumul_diff); + difficulties alt_cumul_diff = = AUTO_VAL_INIT(alt_cumul_diff); + //we use get_last_alt_x_block_cumulative_precise_difficulty for getting both alt chain and main chain diff of given block types + + wide_difficulty_type alt_pos_diff_end = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain, alt_chain_bei.height, true); + wide_difficulty_type alt_pos_diff_begin = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type(), connection_point.height-1, true); + alt_cumul_diff.pos_diff = alt_pos_diff_end- alt_pos_diff_begin; + + wide_difficulty_type alt_pow_diff_end = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain, alt_chain_bei.height, false); + wide_difficulty_type alt_pow_diff_begin = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type(), connection_point.height - 1, false); + alt_cumul_diff.pow_diff = alt_pow_diff_end - alt_pow_diff_begin; + + wide_difficulty_type main_pos_diff_end = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type(), m_db_blocks.size()-1, true); + wide_difficulty_type main_pos_diff_begin = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type(), connection_point.height - 1, true); + main_cumul_diff.pos_diff = main_pos_diff_end - main_pos_diff_begin; + + wide_difficulty_type main_pow_diff_end = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type(), m_db_blocks.size() - 1, false); + wide_difficulty_type main_pow_diff_begin = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type(), connection_point.height - 1, false); + main_cumul_diff.pow_diff = main_pow_diff_end - main_pow_diff_begin; + + //TODO: measurment of precise cumulative difficult + wide_difficulty_type alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff); + wide_difficulty_type main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff); + + if (main < alt) + return true; + else if (main > alt) + return false; + else + { + if (!is_pos_block(main_chain_bei.bl)) + return false; // do not reorganize on the same cummul diff if it's a PoW block + + //in case of simultaneous PoS blocks are happened on the same height (quite common for PoS) + //we also try to weight them to guarantee consensus in network + if (std::memcmp(&main_chain_bei.stake_hash, &proof_alt, sizeof(main_chain_bei.stake_hash)) >= 0) + return false; + + LOG_PRINT_L2("[is_reorganize_required]:TRUE, \"by order of memcmp\" main_stake_hash:" << &main_chain_bei.stake_hash << ", alt_stake_hash" << proof_alt); + return true; + } } else { @@ -4368,7 +4437,7 @@ uint64_t blockchain_storage::get_last_x_block_height(bool pos) const return 0; } //------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type& alt_chain, uint64_t block_height, bool pos) const +wide_difficulty_type blockchain_storage::get_last_alt_x_block_cumulative_precise_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos) const { uint64_t main_chain_first_block = block_height - 1; for (auto it = alt_chain.rbegin(); it != alt_chain.rend(); it++) diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 303765e7..09d2fbd4 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -542,6 +542,7 @@ namespace currency std::string print_alt_chain(alt_chain_type alt_chain); bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc); bool is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt); + wide_difficulty_type get_x_difficulty_after_height(uint64_t height, bool is_pos); bool purge_keyimage_from_big_heap(const crypto::key_image& ki, const crypto::hash& id); bool purge_altblock_keyimages_from_big_heap(const block& b, const crypto::hash& id); bool append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::set& alt_block_keyimages); @@ -609,7 +610,7 @@ namespace currency wide_difficulty_type get_adjusted_cumulative_difficulty_for_next_pos(wide_difficulty_type next_diff)const; wide_difficulty_type get_adjusted_cumulative_difficulty_for_next_alt_pos(alt_chain_type& alt_chain, uint64_t block_height, wide_difficulty_type next_diff, uint64_t connection_height)const; uint64_t get_last_x_block_height(bool pos)const; - wide_difficulty_type get_last_alt_x_block_cumulative_precise_difficulty(alt_chain_type& alt_chain, uint64_t block_height, bool pos)const; + wide_difficulty_type get_last_alt_x_block_cumulative_precise_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos)const; size_t get_current_sequence_factor_for_alt(alt_chain_type& alt_chain, bool pos, uint64_t connection_height)const; }; diff --git a/src/currency_core/blockchain_storage_basic.h b/src/currency_core/blockchain_storage_basic.h index 05709aef..dd3cf354 100644 --- a/src/currency_core/blockchain_storage_basic.h +++ b/src/currency_core/blockchain_storage_basic.h @@ -47,6 +47,7 @@ namespace currency uint64_t block_cumulative_size; wide_difficulty_type cumulative_diff_adjusted; wide_difficulty_type cumulative_diff_precise; + wide_difficulty_type cumulative_diff_precise_adjusted; wide_difficulty_type difficulty; boost::multiprecision::uint128_t already_generated_coins; crypto::hash stake_hash; //TODO: unused field for PoW blocks, subject for refactoring diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 0bb14682..49133c6b 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2670,11 +2670,14 @@ namespace currency wide_difficulty_type get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point, const wide_difficulty_type& difficulty_pow_at_split_point, - const wide_difficulty_type& a_pos_cumulative_difficulty, - const wide_difficulty_type& b_pos_cumulative_difficulty, - const wide_difficulty_type& a_pow_cumulative_difficulty, - const wide_difficulty_type& b_pow_cumulative_difficulty) + const difficulties& a_diff, + const difficulties& b_diff ) { + const wide_difficulty_type& a_pos_cumulative_difficulty = a_diff.pos_diff; + const wide_difficulty_type& b_pos_cumulative_difficulty = b_diff.pos_diff; + const wide_difficulty_type& a_pow_cumulative_difficulty = a_diff.pow_diff; + const wide_difficulty_type& b_pow_cumulative_difficulty = b_diff.pow_diff; + boost::multiprecision::uint1024_t basic_sum = boost::multiprecision::uint1024_t(a_pow_cumulative_difficulty) + (boost::multiprecision::uint1024_t(a_pos_cumulative_difficulty)*difficulty_pow_at_split_point) / difficulty_pos_at_split_point; boost::multiprecision::uint1024_t res = (basic_sum * a_pow_cumulative_difficulty * a_pos_cumulative_difficulty) / (boost::multiprecision::uint1024_t(a_pow_cumulative_difficulty)*a_pos_cumulative_difficulty); diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 05b1be95..5528b073 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -672,12 +672,17 @@ namespace currency std::string utf8_to_lower(const std::string& s); bool utf8_substring_test_case_insensitive(const std::string& match, const std::string& s); // Returns true is 's' contains 'match' (case-insensitive) + struct difficulties + { + wide_difficulty_type pos_diff; + wide_difficulty_type pow_diff; + }; + wide_difficulty_type get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point, const wide_difficulty_type& difficulty_pow_at_split_point, - const wide_difficulty_type& a_pos_cumulative_difficulty, - const wide_difficulty_type& b_pos_cumulative_difficulty, - const wide_difficulty_type& a_pow_cumulative_difficulty, - const wide_difficulty_type& b_pow_cumulative_difficulty); + const difficulties& a_diff, + const difficulties& b_diff + ); } // namespace currency