diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index b5913dc27..39e90f68a 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -409,4 +409,37 @@ namespace cryptonote { } return next_D; } + + // based on original difficulty, but without difficulty_lag + difficulty_type next_difficulty_v6(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) { + size_t length = timestamps.size(); + assert(length == cumulative_difficulties.size()); + if (length <= 1) { + return 1; + } + if (HEIGHT <= DIFFICULTY_RESET_HEIGHT + DIFFICULTY_WINDOW && HEIGHT >= DIFFICULTY_RESET_HEIGHT) { return DIFFICULTY_RESET_LEVEL; } + static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); + assert(length <= DIFFICULTY_WINDOW); + sort(timestamps.begin(), timestamps.end()); + size_t cut_begin, cut_end; + static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); + if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) { + cut_begin = 0; + cut_end = length; + } else { + cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2; + cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT); + } + assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length); + uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin]; + if (time_span == 0) { + time_span = 1; + } + difficulty_type total_work = cumulative_difficulties[cut_end - 1] - cumulative_difficulties[cut_begin]; + assert(total_work > 0); + boost::multiprecision::uint256_t res = (boost::multiprecision::uint256_t(total_work) * target_seconds + time_span - 1) / time_span; + if(res > max128bit) + return 0; // to behave like previous implementation, may be better return max128bit? + return res.convert_to(); + } } diff --git a/src/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h index 3a4edb5e6..53313a389 100644 --- a/src/cryptonote_basic/difficulty.h +++ b/src/cryptonote_basic/difficulty.h @@ -62,6 +62,7 @@ namespace cryptonote difficulty_type next_difficulty_v3(std::vector timestamps, std::vector cumulative_difficulties, uint64_t HEIGHT); difficulty_type next_difficulty_v4(std::vector timestamps, std::vector cumulative_difficulties, uint64_t HEIGHT); difficulty_type next_difficulty_v5(std::vector timestamps, std::vector cumulative_difficulties, uint64_t HEIGHT); + difficulty_type next_difficulty_v6(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT); std::string hex(difficulty_type v); } diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 5d5104125..4dd64a0e7 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -86,11 +86,14 @@ #define DIFFICULTY_WINDOW_V3 144 #define DIFFICULTY_WINDOW_V2 60 #define DIFFICULTY_WINDOW 720 // blocks +#define DIFFICULTY_WINDOW_V4 144 // 12 hours #define DIFFICULTY_LAG 15 // !!! #define DIFFICULTY_CUT 60 // timestamps to cut after sorting +#define DIFFICULTY_CUT_V2 10 // used by v6 difficulty with v4 blocks count #define DIFFICULTY_BLOCKS_COUNT_V3 DIFFICULTY_WINDOW_V3 + 1 // added +1 to make N=N #define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + 1 // added +1 to make N=N #define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG +#define DIFFICULTY_BLOCKS_COUNT_V4 DIFFICULTY_WINDOW_V4 + 1 // new difficulty doesn't have lag #define DIFFICULTY_RESET_HEIGHT 331170// ~July 4, 2021 Pool Independence Day #define DIFFICULTY_RESET_LEVEL 100000000 // 100 mill diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 29f3ad625..85e74666b 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -875,7 +875,7 @@ start: ss << "Re-locked, height " << height << ", tail id " << new_top_hash << (new_top_hash == top_hash ? "" : " (different)") << std::endl; top_hash = new_top_hash; uint8_t version = get_current_hard_fork_version(); - uint64_t difficulty_blocks_count = version <= 17 && version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT; + uint64_t difficulty_blocks_count = version >= 20 ? DIFFICULTY_BLOCKS_COUNT_V4 : version <= 17 && version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT; // ND: Speedup // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty, @@ -955,7 +955,9 @@ start: uint64_t HEIGHT = m_db->height(); difficulty_type diff = next_difficulty(timestamps, difficulties, target, HEIGHT); - if (version <= 17 && version >= 11) { + if (version >= 20) { + diff = next_difficulty_v6(timestamps, difficulties, target, HEIGHT); + } else if (version <= 17 && version >= 11) { diff = next_difficulty_v5(timestamps, difficulties, HEIGHT); } else if (version == 10) { diff = next_difficulty_v4(timestamps, difficulties, HEIGHT); @@ -1049,7 +1051,9 @@ size_t Blockchain::recalculate_difficulties(boost::optional start_heig size_t target = DIFFICULTY_TARGET_V2; difficulty_type recalculated_diff = next_difficulty(timestamps, difficulties, target, HEIGHT); - if (version <= 17 && version >= 11) { + if (version >= 20) { + recalculated_diff = next_difficulty_v6(timestamps, difficulties, target, HEIGHT); + } else if (version <= 17 && version >= 11) { recalculated_diff = next_difficulty_v5(timestamps, difficulties, HEIGHT); } else if (version == 10) { recalculated_diff = next_difficulty_v4(timestamps, difficulties, HEIGHT); @@ -1369,7 +1373,9 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: // calculate the difficulty target for the block and return it difficulty_type next_diff = next_difficulty(timestamps, cumulative_difficulties, target, HEIGHT); - if (version <= 17 && version >= 11) { + if (version >= 20) { + next_diff = next_difficulty_v6(timestamps, cumulative_difficulties, target, HEIGHT); + } else if (version <= 17 && version >= 11) { next_diff = next_difficulty_v5(timestamps, cumulative_difficulties, HEIGHT); } else if (version == 10) { next_diff = next_difficulty_v4(timestamps, cumulative_difficulties, HEIGHT); @@ -1443,7 +1449,11 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, } MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx)); - if (hf_version >= HF_VERSION_FIXED_UNLOCK) + if (hf_version >= HF_VERSION_LONG_UNLOCK) + { + CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_LONG, false, "coinbase transaction transaction has the wrong unlock time=" + << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_LONG); + } else if (hf_version >= HF_VERSION_FIXED_UNLOCK) { CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2);