Skip to content
This repository has been archived by the owner on Jun 30, 2020. It is now read-only.

Commit

Permalink
Replace LWMA-3 with LWMA-4, add v10 fork height
Browse files Browse the repository at this point in the history
  • Loading branch information
wowario committed Nov 8, 2018
1 parent 7bc2142 commit 47bd60b
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 36 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -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.

Expand Down
89 changes: 56 additions & 33 deletions src/cryptonote_basic/difficulty.cpp
Expand Up @@ -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<uint64_t> timestamps, std::vector<difficulty_type> 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_V2 ){
return static_cast<uint64_t>(DIFFICULTY_GUESS);
}

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; }
}

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<uint64_t>(DIFFICULTY_MINIMUM);
}
else {
return static_cast<uint64_t>(next_D);
}

if ( height <= DIFFICULTY_HEIGHT + 1 + N ) { return DIFFICULTY_GUESS; }

// Safely convert out-of-sequence timestamps into > 0 solvetimes.
std::vector<uint64_t>TS(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]; }
}

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); }

prev_D = cumulative_difficulties[N] - cumulative_difficulties[N-1] ;

// 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<uint64_t>(999), (TS[N]-TS[N-10])/10);
}
return next_D;
}
}
3 changes: 1 addition & 2 deletions src/cryptonote_config.h
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/cryptonote_core/blockchain.cpp
Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 47bd60b

Please sign in to comment.