diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index b1862fc89..5ec281d35 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -240,4 +240,55 @@ namespace cryptonote { next_difficulty = static_cast(nextDifficulty); return next_difficulty; } + +// LWMA-2 difficulty algorithm +// Copyright (c) 2017-2018 Zawy, MIT License +// The code below has been tailored to Wownero. +// Don’t be an igit and copy and paste it into +// to your shitcoin without reading the comments in +// https://github.com/zawy12/difficulty-algorithms/issues/3 + + difficulty_type next_difficulty_v3(std::vector timestamps, std::vector cumulative_difficulties, size_t height) { + + int64_t T = DIFFICULTY_TARGET_V2; + int64_t N = DIFFICULTY_WINDOW_V2; + int64_t L(0), ST, sum_3_ST(0), next_D, prev_D; + + assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast(N+1) ); + + if ( cryptonote::MAINNET && height <= DIFFICULTY_HEIGHT ){ + return static_cast(DIFFICULTY_GUESS); + } + + if ( cryptonote::TESTNET && height <= DIFFICULTY_TESTNET_HEIGHT ){ + return static_cast(DIFFICULTY_TESTNET_GUESS); + } + + for ( int64_t i = 1; i <= N; i++ ) { + ST = static_cast(timestamps[i]) - static_cast(timestamps[i-1]); + ST = std::max(-4*T, std::min(ST, 6*T)); + L += ST * i ; + if ( i > N-3 ) { + sum_3_ST += ST; + } + } + next_D = (static_cast(cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L); + + prev_D = cumulative_difficulties[N] - cumulative_difficulties[N-1]; + next_D = std::max((prev_D*67)/100, std::min(next_D, (prev_D*150)/100)); + + if ( sum_3_ST < (8*T)/10) { + next_D = std::max(next_D,(prev_D*108)/100); + } + + if ( cryptonote::MAINNET && next_D < DIFFICULTY_MINIMUM ) { + return static_cast(DIFFICULTY_MINIMUM); + } + else if ( cryptonote::TESTNET && next_D < DIFFICULTY_TESTNET_MINIMUM ) { + return static_cast(DIFFICULTY_TESTNET_MINIMUM); + } + else { + return static_cast(next_D); + } + } } diff --git a/src/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h index 9da643f39..247896e10 100644 --- a/src/cryptonote_basic/difficulty.h +++ b/src/cryptonote_basic/difficulty.h @@ -54,4 +54,5 @@ namespace cryptonote bool check_hash(const crypto::hash &hash, difficulty_type difficulty); difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds); difficulty_type next_difficulty_v2(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds); + difficulty_type next_difficulty_v3(std::vector timestamps, std::vector cumulative_difficulties, size_t height); } diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index fbb57fe4a..ae4d5709f 100755 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -81,7 +81,12 @@ #define DIFFICULTY_CUT 60 // timestamps to cut after sorting #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_HEIGHT 55000 // v9 fork height +#define DIFFICULTY_GUESS 100000000 // 100m +#define DIFFICULTY_MINIMUM 10000000 // minimum difficulty set to 10m +#define DIFFICULTY_TESTNET_HEIGHT 100 +#define DIFFICULTY_TESTNET_GUESS 5069 +#define DIFFICULTY_TESTNET_MINIMUM 4069 #define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 DIFFICULTY_TARGET_V1 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS #define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2 DIFFICULTY_TARGET_V2 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 68b339f4d..90424c739 100755 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -105,6 +105,7 @@ static const struct { //{ 1, 1, 0, 1341378000 }, { 7, 1, 0, 1519605000 }, { 8, 10, 0, 1523255371 }, + { 9, 100, 0, 1537370510 }, }; static const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)(1)); @@ -785,10 +786,10 @@ difficulty_type Blockchain::get_difficulty_for_next_block() uint8_t version = get_current_hard_fork_version(); size_t difficulty_blocks_count; - if (version == 7) { - difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT; - } else { + if (version >= 8) { difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V2; + } else { + difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT; } // ND: Speedup @@ -832,8 +833,12 @@ difficulty_type Blockchain::get_difficulty_for_next_block() size_t target = DIFFICULTY_TARGET_V2; if (version == 7) { return next_difficulty(timestamps, difficulties, target); - } else { + } + else if (version == 8) { return next_difficulty_v2(timestamps, difficulties, target); + } + else { + return next_difficulty_v3(timestamps, difficulties, height); } } //------------------------------------------------------------------ @@ -984,10 +989,11 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: std::vector cumulative_difficulties; uint8_t version = get_current_hard_fork_version(); size_t difficulty_blocks_count; - if (version == 7) { - difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT; - } else { + size_t height = m_db->height(); + if (version >= 8) { difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V2; + } else { + difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT; } // if the alt chain isn't long enough to calculate the difficulty target @@ -1013,7 +1019,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: } // make sure we haven't accidentally grabbed too many blocks...maybe don't need this check? - CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= difficulty_blocks_count, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << DIFFICULTY_BLOCKS_COUNT); + CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= difficulty_blocks_count, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << difficulty_blocks_count); for (auto it : alt_chain) { @@ -1042,12 +1048,16 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: // FIXME: This will fail if fork activation heights are subject to voting size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; - + // calculate the difficulty target for the block and return it if (version == 7) { return next_difficulty(timestamps, cumulative_difficulties, target); - } else { + } + else if (version == 8) { return next_difficulty_v2(timestamps, cumulative_difficulties, target); + } + else { + return next_difficulty_v3(timestamps, cumulative_difficulties, height); } } @@ -3212,10 +3222,10 @@ bool Blockchain::check_block_timestamp(std::vector& timestamps, const bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) const { LOG_PRINT_L3("Blockchain::" << __func__); - uint64_t cryptonote_block_future_time_limit = get_current_hard_fork_version() < 7 ? CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT : CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2; + uint64_t cryptonote_block_future_time_limit = get_current_hard_fork_version() >= 8 ? CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 : CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT; if(b.timestamp > get_adjusted_time() + cryptonote_block_future_time_limit) { - MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours"); + MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 10 minutes"); return false; }