diff --git a/README.md b/README.md index 66de4e32c..96ab39e2c 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ Dates are provided in the format YYYY-MM-DD. | 1 | 2018-04-01 | v7 | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs | 6969 | 2018-04-24 | v8 | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4 | 53666 | 2018-10-06 | v9 | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS +| 63469 | 2018-11-11 | v10 | v0.4.0.0 | v0.4.0.0 | LWMA v4 X's indicate that these details have not been determined as of commit date. diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index 530fe81a6..927e1baf7 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -285,42 +285,65 @@ namespace cryptonote { } } - // LWMA-3 difficulty algorithm + // LWMA-4 difficulty algorithm // Copyright (c) 2017-2018 Zawy, MIT License + // https://github.com/zawy12/difficulty-algorithms/issues/3 difficulty_type next_difficulty_v4(std::vector timestamps, std::vector cumulative_difficulties, size_t height) { - uint64_t T = DIFFICULTY_TARGET_V2; - uint64_t N = DIFFICULTY_WINDOW_V2; - uint64_t L(0), ST, sum_3_ST(0), next_D, prev_D, this_timestamp, previous_timestamp; - + uint64_t T = DIFFICULTY_TARGET_V2; + uint64_t N = DIFFICULTY_WINDOW_V2; // N=45, 60, and 90 for T=600, 120, 60. + uint64_t L(0), ST(0), next_D, prev_D, avg_D, i; + assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 ); + + if ( height <= DIFFICULTY_HEIGHT + 1 + N ) { return DIFFICULTY_GUESS; } + + // Safely convert out-of-sequence timestamps into > 0 solvetimes. + std::vectorTS(N+1); + TS[0] = timestamps[0]; + for ( i = 1; i <= N; i++) { + if ( timestamps[i] > TS[i-1] ) { TS[i] = timestamps[i]; } + else { TS[i] = TS[i-1]; } + } - if ( height == DIFFICULTY_HEIGHT_V2 ){ - return static_cast(DIFFICULTY_GUESS); - } + for ( i = 1; i <= N; i++) { + // Ignore long solvetimes if they were preceeded by 3 or 6 fast solves. + if ( i > 4 && TS[i]-TS[i-1] > 4*T && TS[i-1] - TS[i-4] < (16*T)/10 ) { ST = 2*T; } + else if ( i > 7 && TS[i]-TS[i-1] > 4*T && TS[i-1] - TS[i-7] < 4*T ) { ST = 2*T; } + else { // Assume normal conditions, so get ST. + // LWMA drops too much from long ST, so limit drops with a 5*T limit + ST = std::min(5*T ,TS[i] - TS[i-1]); + } + L += ST * i ; + } + if (L < N*N*T/20 ) { L = N*N*T/20; } + avg_D = ( cumulative_difficulties[N] - cumulative_difficulties[0] )/ N; + + // Prevent round off error for small D and overflow for large D. + if (avg_D > 2000000*N*N*T) { + next_D = (avg_D/(200*L))*(N*(N+1)*T*97); + } + else { next_D = (avg_D*N*(N+1)*T*97)/(200*L); } - previous_timestamp = timestamps[0]; - for ( uint64_t i = 1; i <= N; i++) { - if ( timestamps[i] > previous_timestamp ) { - this_timestamp = timestamps[i]; - } else { this_timestamp = previous_timestamp+1; } - ST = std::min(6*T ,this_timestamp - previous_timestamp); - previous_timestamp = this_timestamp; - L += ST * i ; - if ( i > N-3 ) { sum_3_ST += ST; } - } + prev_D = cumulative_difficulties[N] - cumulative_difficulties[N-1] ; - next_D = ((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 ( next_D < DIFFICULTY_MINIMUM ) { - return static_cast(DIFFICULTY_MINIMUM); - } - else { - return static_cast(next_D); - } + // Apply 10% jump rule. + if ( ( TS[N] - TS[N-1] < (2*T)/10 ) || + ( TS[N] - TS[N-2] < (5*T)/10 ) || + ( TS[N] - TS[N-3] < (8*T)/10 ) ) + { + next_D = std::max( next_D, std::min( (prev_D*110)/100, (105*avg_D)/100 ) ); + } + // Make all insignificant digits zero for easy reading. + i = 1000000000; + while (i > 1) { + if ( next_D > i*100 ) { next_D = ((next_D+i/2)/i)*i; break; } + else { i /= 10; } + } + // Make least 3 digits equal avg of past 10 solvetimes. + if ( next_D > 100000 ) { + next_D = ((next_D+500)/1000)*1000 + std::min(static_cast(999), (TS[N]-TS[N-10])/10); + } + return next_D; } } diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index bf446a81f..17b0aaa10 100755 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -82,8 +82,7 @@ #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 53666 // v9 fork height -#define DIFFICULTY_HEIGHT_V2 777777 // v10 fork height +#define DIFFICULTY_HEIGHT 63469 // v10 fork height #define DIFFICULTY_GUESS 40000000 // difficulty at fork 40m #define DIFFICULTY_MINIMUM 25000000 // minimum difficulty set to 25m diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 8c73819f1..396235772 100755 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -93,6 +93,7 @@ static const struct { { 7, 1, 0, 1519605000 }, { 8, 6969, 0, 1524214739 }, { 9, 53666, 0, 1538689773 }, + { 10, 63469, 0, 1541700352 }, }; static const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)(0)); @@ -1061,7 +1062,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: return next_difficulty_v2(timestamps, cumulative_difficulties, target); } else if (version == 9) { - return next_difficulty_v2(timestamps, cumulative_difficulties, height); + return next_difficulty_v3(timestamps, cumulative_difficulties, height); } else { return next_difficulty_v4(timestamps, cumulative_difficulties, height);