From c9f93364ad0cea62bb97fe85e588d2afaf12d404 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 19 Jul 2019 18:39:00 +0200 Subject: [PATCH] changed difficulty adjustment --- src/currency_core/blockchain_storage.cpp | 73 ++++++++++++++----- src/currency_core/blockchain_storage.h | 3 +- src/currency_core/core_runtime_config.h | 2 + src/currency_core/currency_config.h | 7 ++ src/currency_core/currency_format_utils.cpp | 2 +- src/currency_core/difficulty.cpp | 38 +++++++++- src/currency_core/difficulty.h | 3 +- tests/core_tests/block_validation.cpp | 4 +- tests/core_tests/chaingen.cpp | 2 +- .../functional_tests/difficulty_analysis.cpp | 2 +- 10 files changed, 109 insertions(+), 27 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index a8e4b786..2c205162 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -69,14 +69,6 @@ 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) @@ -979,12 +971,21 @@ wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) con wide_difficulty_type& dif = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty; TIME_MEASURE_FINISH_PD(target_calculating_enum_blocks); TIME_MEASURE_START_PD(target_calculating_calc); - dif = next_difficulty(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); + if (m_db_blocks.size() > ZANO_HARDFORK_1_AFTER_HEIGHT) + { + dif = next_difficulty_2(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); + } + else + { + dif = next_difficulty_1(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); + } + + TIME_MEASURE_FINISH_PD(target_calculating_calc); return dif; } //------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_next_diff_conditional2(bool pos, const alt_chain_type& alt_chain, uint64_t split_height) const +wide_difficulty_type blockchain_storage::get_next_diff_conditional2(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const { CRITICAL_REGION_LOCAL(m_read_lock); std::vector timestamps; @@ -1007,7 +1008,13 @@ wide_difficulty_type blockchain_storage::get_next_diff_conditional2(bool pos, co return true; }; enum_blockchain(cb, alt_chain, split_height); - return next_difficulty(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); + + wide_difficulty_type diff = 0; + if(abei.height > ZANO_HARDFORK_1_AFTER_HEIGHT) + diff = next_difficulty_2(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); + else + diff = next_difficulty_1(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); + return diff; } //------------------------------------------------------------------ wide_difficulty_type blockchain_storage::get_cached_next_difficulty(bool pos) const @@ -1066,7 +1073,7 @@ wide_difficulty_type blockchain_storage::get_next_difficulty_for_alternative_cha commulative_difficulties.push_back(m_db_blocks[i]->cumulative_diff_precise); } - return next_difficulty(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET:DIFFICULTY_POW_TARGET); + return next_difficulty_1(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET:DIFFICULTY_POW_TARGET); } //------------------------------------------------------------------ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t height, bool pos) const @@ -1204,7 +1211,12 @@ bool blockchain_storage::create_block_template(block& b, size_t median_size; boost::multiprecision::uint128_t already_generated_coins; CRITICAL_REGION_BEGIN(m_read_lock); - b.major_version = CURRENT_BLOCK_MAJOR_VERSION; + height = m_db_blocks.size(); + if(height <= m_core_runtime_config.hard_fork1_starts_after_height) + b.major_version = BLOCK_MAJOR_VERSION_INITAL; + else + b.major_version = CURRENT_BLOCK_MAJOR_VERSION; + b.minor_version = CURRENT_BLOCK_MINOR_VERSION; b.prev_id = get_top_block_id(); b.timestamp = m_core_runtime_config.get_core_time(); @@ -1221,7 +1233,7 @@ bool blockchain_storage::create_block_template(block& b, CHECK_AND_ASSERT_MES(diffic, false, "difficulty owverhead."); - height = m_db_blocks.size(); + median_size = m_db_current_block_cumul_sz_limit / 2; already_generated_coins = m_db_blocks.back()->already_generated_coins; @@ -1507,7 +1519,7 @@ 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_diff_conditional2(pos_block, alt_chain, connection_height); + wide_difficulty_type current_diff = get_next_diff_conditional2(pos_block, alt_chain, connection_height, abei); CHECK_AND_ASSERT_MES_CUSTOM(current_diff, false, bvc.m_verification_failed = true, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); @@ -1716,7 +1728,7 @@ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_ 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); + difficulties alt_cumul_diff = AUTO_VAL_INIT(alt_cumul_diff); //we use get_last_alt_x_block_cumulative_precise_adj_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_adj_difficulty(alt_chain, alt_chain_bei.height, true); @@ -2466,7 +2478,7 @@ bool blockchain_storage::forecast_difficulty(std::vector(); } - wide_difficulty_type next_difficulty(vector& timestamps, vector& cumulative_difficulties, size_t target_seconds) + wide_difficulty_type next_difficulty_1(vector& timestamps, vector& cumulative_difficulties, size_t target_seconds) { // timestamps - first is latest, back - is oldest timestamps @@ -220,4 +220,40 @@ namespace currency { } return summ / devider; } + + wide_difficulty_type next_difficulty_2(vector& timestamps, vector& cumulative_difficulties, size_t target_seconds) + { + + // timestamps - first is latest, back - is oldest timestamps + if (timestamps.size() > DIFFICULTY_WINDOW) + { + timestamps.resize(DIFFICULTY_WINDOW); + cumulative_difficulties.resize(DIFFICULTY_WINDOW); + } + + + size_t length = timestamps.size(); + CHECK_AND_ASSERT_MES(length == cumulative_difficulties.size(), 0, "Check \"length == cumulative_difficulties.size()\" failed"); + if (length <= 1) + { + return DIFFICULTY_STARTER; + } + static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); + + CHECK_AND_ASSERT_MES(length <= DIFFICULTY_WINDOW, 0, "length <= DIFFICULTY_WINDOW check failed, length=" << length); + + sort(timestamps.begin(), timestamps.end(), std::greater()); + + static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); + wide_difficulty_type dif_slow = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW, DIFFICULTY_CUT / 2, DIFFICULTY_CUT / 2); + wide_difficulty_type dif_medium = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW / 3, DIFFICULTY_CUT / 8, DIFFICULTY_CUT / 12); + uint64_t devider = 1; + wide_difficulty_type summ = dif_slow; + if (dif_medium != 0) + { + summ += dif_medium; + ++devider; + } + return summ / devider; + } } diff --git a/src/currency_core/difficulty.h b/src/currency_core/difficulty.h index 529389e3..ab97f142 100644 --- a/src/currency_core/difficulty.h +++ b/src/currency_core/difficulty.h @@ -19,7 +19,8 @@ namespace currency typedef boost::multiprecision::uint128_t wide_difficulty_type; bool check_hash(const crypto::hash &hash, wide_difficulty_type difficulty); - wide_difficulty_type next_difficulty(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds); + wide_difficulty_type next_difficulty_1(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds); + wide_difficulty_type next_difficulty_2(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds); uint64_t difficulty_to_boundary(wide_difficulty_type difficulty); void difficulty_to_boundary_long(wide_difficulty_type difficulty, crypto::hash& result); } diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index d01b65c8..22973321 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -21,7 +21,7 @@ namespace for (size_t i = 0; i < new_block_count; ++i) { block blk_next; - wide_difficulty_type diffic = next_difficulty(timestamps, cummulative_difficulties, DIFFICULTY_POW_TARGET); + wide_difficulty_type diffic = next_difficulty_1(timestamps, cummulative_difficulties, DIFFICULTY_POW_TARGET); if (!generator.construct_block_manually(blk_next, blk_prev, miner_account, test_generator::bf_timestamp | test_generator::bf_diffic, 0, 0, blk_prev.timestamp, crypto::hash(), diffic)) return false; @@ -152,7 +152,7 @@ bool gen_block_invalid_nonce::generate(std::vector& events) co return false; // Create invalid nonce - wide_difficulty_type diffic = next_difficulty(timestamps, commulative_difficulties, DIFFICULTY_POW_TARGET); + wide_difficulty_type diffic = next_difficulty_1(timestamps, commulative_difficulties, DIFFICULTY_POW_TARGET); CHECK_AND_ASSERT_MES(diffic > 1, false, "diffic > 1 validation failed"); const block& blk_last = boost::get(events.back()); uint64_t timestamp = blk_last.timestamp; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 0faf29d9..e28afd2d 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -673,7 +673,7 @@ currency::wide_difficulty_type test_generator::get_difficulty_for_next_block(con timestamps.push_back(blocks[i]->b.timestamp); commulative_difficulties.push_back(blocks[i]->cumul_difficulty); } - return next_difficulty(timestamps, commulative_difficulties, pow ? DIFFICULTY_POW_TARGET : DIFFICULTY_POS_TARGET); + return next_difficulty_1(timestamps, commulative_difficulties, pow ? DIFFICULTY_POW_TARGET : DIFFICULTY_POS_TARGET); } currency::wide_difficulty_type test_generator::get_cumul_difficulty_for_next_block(const crypto::hash& head_id, bool pow) const diff --git a/tests/functional_tests/difficulty_analysis.cpp b/tests/functional_tests/difficulty_analysis.cpp index be994253..0af4d4d8 100644 --- a/tests/functional_tests/difficulty_analysis.cpp +++ b/tests/functional_tests/difficulty_analysis.cpp @@ -313,7 +313,7 @@ void run_emulation(const std::string& path) PERFORME_SIMULATION_FOR_FUNCTION(bbr_next_difficulty_configurable, BBR_DIFFICULTY_WINDOW, BBR_DIFFICULTY_CUT, BBR_DIFFICULTY_CUT); PERFORME_SIMULATION_FOR_FUNCTION(bbr_next_difficulty_configurable, 500, 60, 60); PERFORME_SIMULATION_FOR_FUNCTION(bbr_next_difficulty_configurable, 300, 60, 60); - PERFORME_SIMULATION_FOR_FUNCTION_NO_WINDOW(currency::next_difficulty); + PERFORME_SIMULATION_FOR_FUNCTION_NO_WINDOW(currency::next_difficulty_1); print_blocks(result_blocks, path + "result.txt"); LOG_PRINT_L0("Done");