From 667a4dec8a687c8c39989311653e0cdba4e4cf50 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 18 Jun 2019 01:15:33 +0300 Subject: [PATCH] inital implementation of PoS improvements: comparing function, diff tracing, block version --- contrib/epee/include/misc_log_ex.h | 17 +++ src/currency_core/blockchain_storage.cpp | 143 ++++++++++++++------ src/currency_core/blockchain_storage.h | 2 +- src/currency_core/currency_config.h | 2 +- src/currency_core/currency_format_utils.cpp | 33 +++++ src/currency_core/currency_format_utils.h | 9 ++ 6 files changed, 161 insertions(+), 45 deletions(-) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index c8bd69e1..6cc40d13 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -251,6 +251,23 @@ DISABLE_VS_WARNINGS(4100) custom_code; \ } + +#define CATCH_ENTRY_WITH_FORWARDING_EXCEPTION() \ + catch(const std::exception& ex) \ +{ \ + (void)(ex); \ + LOG_ERROR("Exception at [" << LOCATION_SS << "], what=" << ex.what()); \ + throw std::runtime_error(std::string("[EXCEPTION FORWARDED]: ") + ex.what()); \ +} \ + catch(...) \ +{ \ + LOG_ERROR("Exception at [" << LOCATION_SS << "], generic unknown exception \"...\""); \ + throw std::runtime_error("[EXCEPTION FORWARDED]"); \ + custom_code; \ +} + + + #define NESTED_TRY_ENTRY() try { TRY_ENTRY(); #define NESTED_CATCH_ENTRY(location) \ diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 03d989af..9f151536 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -69,6 +69,16 @@ using namespace currency; #define BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION 18000 #endif +#define BLOCK_MAJOR_VERSION_INITAL 1 + +#ifndef TESTNET +#define ZANO_HARDFORK_1_AFTER_HEIGHT ?? +#else +#define ZANO_HARDFORK_1_AFTER_HEIGHT ?? +#endif + + + DISABLE_VS_WARNINGS(4267) namespace @@ -1557,7 +1567,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: << ENDL << "HEIGHT " << abei.height << ", difficulty: " << abei.difficulty << ", cumul_diff_precise: " << abei.cumulative_diff_precise << ", cumul_diff_adj: " << abei.cumulative_diff_adjusted << " (current mainchain cumul_diff_adj: " << m_db_blocks.back()->cumulative_diff_adjusted << ", ki lookup total: " << ki_lookup_total <<")" , LOG_LEVEL_0); - if (is_reorganize_required(*m_db_blocks.back(), abei, proof)) + if (is_reorganize_required(*m_db_blocks.back(), alt_chain, proof)) { auto a = epee::misc_utils::create_scope_leave_handler([&]() { m_is_reorganize_in_process = false; }); CHECK_AND_ASSERT_THROW_MES(!m_is_reorganize_in_process, "Detected recursive reorganzie"); @@ -1586,26 +1596,43 @@ 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); } //------------------------------------------------------------------ -bool blockchain_storage::is_reorganize_required(const block_extended_info& main_chain_bei, const block_extended_info& alt_chain_bei, const crypto::hash& proof_alt) +bool blockchain_storage::is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt) { - 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) - return false; - else // main_chain_bei.cumulative_diff_adjusted == alt_chain_bei.cumulative_diff_adjusted - { - if (!is_pos_block(main_chain_bei.bl)) - return false; // do not reorganize on the same cummul diff if it's a PoW block + //alt_chain - back is latest(top), first - connection with main chain + const block_extended_info& alt_chain_bei = alt_chain.back()->second; - //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) + if (alt_chain_bei.bl.major_version == BLOCK_MAJOR_VERSION_INITAL) + { + 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) 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 // main_chain_bei.cumulative_diff_adjusted == alt_chain_bei.cumulative_diff_adjusted + { + 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 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; + + } + else + { + ASSERT_MES_AND_THROW("Unknown version of block"); } } + //------------------------------------------------------------------ bool blockchain_storage::pre_validate_relayed_block(block& bl, block_verification_context& bvc, const crypto::hash& id)const { @@ -4446,40 +4473,70 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt if (is_pos_bl) bei.stake_hash = proof_hash; - //precise difficulty - difficulty used to calculate next difficulty - uint64_t last_x_h = get_last_x_block_height(is_pos_bl); - if (!last_x_h) - bei.cumulative_diff_precise = current_diffic; - else - bei.cumulative_diff_precise = m_db_blocks[last_x_h]->cumulative_diff_precise + current_diffic; - if (m_db_blocks.size()) + + ////////////////////////////////////////////////////////////////////////// + if (bei.bl.major_version == BLOCK_MAJOR_VERSION_INITAL) { - bei.cumulative_diff_adjusted = m_db_blocks.back()->cumulative_diff_adjusted; - } + //precise difficulty - difficulty used to calculate next difficulty + uint64_t last_x_h = get_last_x_block_height(is_pos_bl); + if (!last_x_h) + bei.cumulative_diff_precise = current_diffic; + else + bei.cumulative_diff_precise = m_db_blocks[last_x_h]->cumulative_diff_precise + current_diffic; - //adjusted difficulty - difficulty used to switch blockchain - wide_difficulty_type cumulative_diff_delta = 0; - if (is_pos_bl) - cumulative_diff_delta = get_adjusted_cumulative_difficulty_for_next_pos(current_diffic); - else - cumulative_diff_delta = current_diffic; + if (m_db_blocks.size()) + { + bei.cumulative_diff_adjusted = m_db_blocks.back()->cumulative_diff_adjusted; + } + + //adjusted difficulty - difficulty used to switch blockchain + wide_difficulty_type cumulative_diff_delta = 0; + if (is_pos_bl) + cumulative_diff_delta = get_adjusted_cumulative_difficulty_for_next_pos(current_diffic); + else + cumulative_diff_delta = current_diffic; - size_t sequence_factor = get_current_sequence_factor(is_pos_bl); - if (bei.height >= m_core_runtime_config.pos_minimum_heigh) - cumulative_diff_delta = correct_difficulty_with_sequence_factor(sequence_factor, cumulative_diff_delta); - - if (bei.height > BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION && is_pos_bl && sequence_factor > 20) + size_t sequence_factor = get_current_sequence_factor(is_pos_bl); + if (bei.height >= m_core_runtime_config.pos_minimum_heigh) + cumulative_diff_delta = correct_difficulty_with_sequence_factor(sequence_factor, cumulative_diff_delta); + + if (bei.height > BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION && is_pos_bl && sequence_factor > 20) + { + LOG_PRINT_L0("Block with id: " << id + << " has too big sequence_factor = " << sequence_factor); + purge_block_data_from_blockchain(bl, tx_processed_count); + bvc.m_verification_failed = true; + return false; + } + + bei.cumulative_diff_adjusted += cumulative_diff_delta; + }else if(bei.bl.major_version == CURRENT_BLOCK_MAJOR_VERSION) { - LOG_PRINT_L0("Block with id: " << id - << " has too big sequence_factor = " << sequence_factor); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } + //precise difficulty - difficulty used to calculate next difficulty + uint64_t last_x_h = get_last_x_block_height(is_pos_bl); + if (!last_x_h) + bei.cumulative_diff_precise = current_diffic; + else + bei.cumulative_diff_precise = m_db_blocks[last_x_h]->cumulative_diff_precise + current_diffic; + + if (m_db_blocks.size()) + { + bei.cumulative_diff_adjusted = m_db_blocks[last_x_h]->cumulative_diff_adjusted; + } + + //adjusted difficulty - difficulty used to switch blockchain + wide_difficulty_type cumulative_diff_delta = current_diffic; + + size_t sequence_factor = get_current_sequence_factor(is_pos_bl); + if (bei.height >= m_core_runtime_config.pos_minimum_heigh) + cumulative_diff_delta = correct_difficulty_with_sequence_factor(sequence_factor, cumulative_diff_delta); + + bei.cumulative_diff_adjusted += cumulative_diff_delta; + } + ////////////////////////////////////////////////////////////////////////// - bei.cumulative_diff_adjusted += cumulative_diff_delta; //etc bei.already_generated_coins = already_generated_coins + base_reward; diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 580afe81..1161b33f 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -537,7 +537,7 @@ namespace currency bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc); 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 block_extended_info& alt_chain_bei, const crypto::hash& proof_alt); + bool is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt); 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); diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 060f4d2d..142558e3 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -19,7 +19,7 @@ #define CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x3678 // integrated addresses start with 'iZ' #define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10 #define CURRENT_TRANSACTION_VERSION 1 -#define CURRENT_BLOCK_MAJOR_VERSION 1 +#define CURRENT_BLOCK_MAJOR_VERSION 2 #define CURRENT_BLOCK_MINOR_VERSION 0 #define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2 #define CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT 60*20 diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 28235ed4..24cf4862 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2667,4 +2667,37 @@ namespace currency return false; } + + 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) + { + 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); + + if (res > boost::math::tools::max_value()) + { + ASSERT_MES_AND_THROW("[INTERNAL ERROR]: Failed to get_a_to_b_relative_cumulative_difficulty, res = " << res << ENDL + << ", difficulty_pos_at_split_point: " << difficulty_pos_at_split_point << ENDL + << ", difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL + << ", a_pos_cumulative_difficulty:" << a_pos_cumulative_difficulty << ENDL + << ", b_pos_cumulative_difficulty:" << b_pos_cumulative_difficulty << ENDL + << ", a_pow_cumulative_difficulty:" << a_pow_cumulative_difficulty << ENDL + << ", b_pow_cumulative_difficulty:" << b_pow_cumulative_difficulty << ENDL + ); + } + TRY_ENTRY(); + wide_difficulty_type short_res = res.convert_to(); + return short_res; + CATCH_ENTRY_WITH_FORWARDING_EXCEPTION(); + } + + + } // namespace currency + + diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 01b7328c..05b1be95 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -317,6 +317,7 @@ namespace currency bool parse_amount(uint64_t& amount, const std::string& str_amount); + bool unserialize_block_complete_entry(const COMMAND_RPC_GET_BLOCKS_FAST::response& serialized, COMMAND_RPC_GET_BLOCKS_DIRECT::response& unserialized); @@ -670,6 +671,14 @@ namespace currency std::string utf8_to_upper(const std::string& s); 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) + + 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); + } // namespace currency