difficulty is fun
This commit is contained in:
parent
aa7564806d
commit
2ddaa7835c
|
@ -33,6 +33,7 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <boost/math/special_functions/round.hpp>
|
||||||
|
|
||||||
#include "int-util.h"
|
#include "int-util.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
@ -121,10 +122,10 @@ namespace cryptonote {
|
||||||
|
|
||||||
uint64_t next_difficulty_64(std::vector<std::uint64_t> timestamps, std::vector<uint64_t> cumulative_difficulties, size_t target_seconds) {
|
uint64_t next_difficulty_64(std::vector<std::uint64_t> timestamps, std::vector<uint64_t> cumulative_difficulties, size_t target_seconds) {
|
||||||
|
|
||||||
if(timestamps.size() > DIFFICULTY_WINDOW)
|
if(timestamps.size() > DIFFICULTY_WINDOW_V3)
|
||||||
{
|
{
|
||||||
timestamps.resize(DIFFICULTY_WINDOW);
|
timestamps.resize(DIFFICULTY_WINDOW_V3);
|
||||||
cumulative_difficulties.resize(DIFFICULTY_WINDOW);
|
cumulative_difficulties.resize(DIFFICULTY_WINDOW_V3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,17 +134,17 @@ namespace cryptonote {
|
||||||
if (length <= 1) {
|
if (length <= 1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
static_assert(DIFFICULTY_WINDOW_V3 >= 2, "Window is too small");
|
||||||
assert(length <= DIFFICULTY_WINDOW);
|
assert(length <= DIFFICULTY_WINDOW_V3);
|
||||||
sort(timestamps.begin(), timestamps.end());
|
sort(timestamps.begin(), timestamps.end());
|
||||||
size_t cut_begin, cut_end;
|
size_t cut_begin, cut_end;
|
||||||
static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large");
|
static_assert(2 * DIFFICULTY_CUT_V2 <= DIFFICULTY_WINDOW_V3 - 2, "Cut length is too large");
|
||||||
if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) {
|
if (length <= DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) {
|
||||||
cut_begin = 0;
|
cut_begin = 0;
|
||||||
cut_end = length;
|
cut_end = length;
|
||||||
} else {
|
} else {
|
||||||
cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2;
|
cut_begin = (length - (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) + 1) / 2;
|
||||||
cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT);
|
cut_end = cut_begin + (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2);
|
||||||
}
|
}
|
||||||
assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length);
|
assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length);
|
||||||
uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin];
|
uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin];
|
||||||
|
@ -200,7 +201,7 @@ namespace cryptonote {
|
||||||
return check_hash_128(hash, difficulty);
|
return check_hash_128(hash, difficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
|
||||||
//cutoff DIFFICULTY_LAG
|
//cutoff DIFFICULTY_LAG
|
||||||
if(timestamps.size() > DIFFICULTY_WINDOW)
|
if(timestamps.size() > DIFFICULTY_WINDOW)
|
||||||
{
|
{
|
||||||
|
@ -214,6 +215,8 @@ namespace cryptonote {
|
||||||
if (length <= 1) {
|
if (length <= 1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// reset difficulty for solo mining to 100 million
|
||||||
|
if (HEIGHT <= 331170 + DIFFICULTY_WINDOW && HEIGHT >= 331170) { return 100000000; }
|
||||||
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
||||||
assert(length <= DIFFICULTY_WINDOW);
|
assert(length <= DIFFICULTY_WINDOW);
|
||||||
sort(timestamps.begin(), timestamps.end());
|
sort(timestamps.begin(), timestamps.end());
|
||||||
|
@ -254,4 +257,193 @@ namespace cryptonote {
|
||||||
return "0x" + s;
|
return "0x" + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LWMA difficulty algorithm
|
||||||
|
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3
|
||||||
|
// Copyright (c) 2017-2018 Zawy
|
||||||
|
difficulty_type next_difficulty_v2(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
|
||||||
|
const int64_t T = static_cast<int64_t>(target_seconds);
|
||||||
|
size_t N = DIFFICULTY_WINDOW_V2;
|
||||||
|
if (timestamps.size() < 4) {
|
||||||
|
return 1;
|
||||||
|
} else if ( timestamps.size() < N+1 ) {
|
||||||
|
N = timestamps.size() - 1;
|
||||||
|
} else {
|
||||||
|
timestamps.resize(N+1);
|
||||||
|
cumulative_difficulties.resize(N+1);
|
||||||
|
}
|
||||||
|
const double adjust = 0.998;
|
||||||
|
const double k = N * (N + 1) / 2;
|
||||||
|
double LWMA(0), sum_inverse_D(0), harmonic_mean_D(0), nextDifficulty(0);
|
||||||
|
int64_t solveTime(0);
|
||||||
|
uint64_t difficulty(0), next_difficulty(0);
|
||||||
|
for (size_t i = 1; i <= N; i++) {
|
||||||
|
solveTime = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i - 1]);
|
||||||
|
solveTime = std::min<int64_t>((T * 7), std::max<int64_t>(solveTime, (-7 * T)));
|
||||||
|
difficulty = static_cast<uint64_t>(cumulative_difficulties[i] - cumulative_difficulties[i - 1]);
|
||||||
|
LWMA += (int64_t)(solveTime * i) / k;
|
||||||
|
sum_inverse_D += 1 / static_cast<double>(difficulty);
|
||||||
|
}
|
||||||
|
harmonic_mean_D = N / sum_inverse_D;
|
||||||
|
if (static_cast<int64_t>(boost::math::round(LWMA)) < T / 20)
|
||||||
|
LWMA = static_cast<double>(T / 20);
|
||||||
|
|
||||||
|
nextDifficulty = harmonic_mean_D * T / LWMA * adjust;
|
||||||
|
next_difficulty = static_cast<uint64_t>(nextDifficulty);
|
||||||
|
return next_difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LWMA-2
|
||||||
|
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_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<uint64_t>(N+1) );
|
||||||
|
for ( int64_t i = 1; i <= N; i++ ) {
|
||||||
|
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(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<int64_t>(cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L);
|
||||||
|
prev_D = static_cast<int64_t>(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);
|
||||||
|
}
|
||||||
|
return static_cast<uint64_t>(next_D);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LWMA-4
|
||||||
|
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
|
||||||
|
uint64_t T = DIFFICULTY_TARGET_V2;
|
||||||
|
uint64_t N = DIFFICULTY_WINDOW_V2;
|
||||||
|
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 <= 63469 + 1) { return 100000069; }
|
||||||
|
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++) {
|
||||||
|
if ( i > 4 && TS[i]-TS[i-1] > 5*T && TS[i-1] - TS[i-4] < (14*T)/10 ) { ST = 2*T; }
|
||||||
|
else if ( i > 7 && TS[i]-TS[i-1] > 5*T && TS[i-1] - TS[i-7] < 4*T ) { ST = 2*T; }
|
||||||
|
else {
|
||||||
|
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 = static_cast<uint64_t>(( cumulative_difficulties[N] - cumulative_difficulties[0] )/ N);
|
||||||
|
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 = static_cast<uint64_t>(cumulative_difficulties[N] - cumulative_difficulties[N-1]);
|
||||||
|
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 ) );
|
||||||
|
}
|
||||||
|
i = 1000000000;
|
||||||
|
while (i > 1) {
|
||||||
|
if ( next_D > i*100 ) { next_D = ((next_D+i/2)/i)*i; break; }
|
||||||
|
else { i /= 10; }
|
||||||
|
}
|
||||||
|
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 static_cast<uint64_t>(next_D);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LWMA-1 difficulty algorithm
|
||||||
|
// Copyright (c) 2017-2019 Zawy, MIT License
|
||||||
|
// https://github.com/zawy12/difficulty-algorithms/issues/3
|
||||||
|
difficulty_type next_difficulty_v5(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
|
||||||
|
uint64_t T = DIFFICULTY_TARGET_V2;
|
||||||
|
uint64_t N = DIFFICULTY_WINDOW_V3;
|
||||||
|
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
|
||||||
|
|
||||||
|
if (HEIGHT >= 81769 && HEIGHT < 81769 + N) { return 10000000; }
|
||||||
|
assert(timestamps.size() == N+1);
|
||||||
|
|
||||||
|
// hardcoding previously erroneously calculated difficulty entries
|
||||||
|
if(HEIGHT == 307686) return 25800000;
|
||||||
|
if(HEIGHT == 307692) return 1890000;
|
||||||
|
if(HEIGHT == 307735) return 17900000;
|
||||||
|
if(HEIGHT == 307742) return 21300000;
|
||||||
|
if(HEIGHT == 307750) return 10900000;
|
||||||
|
if(HEIGHT == 307766) return 2960000;
|
||||||
|
|
||||||
|
uint64_t i, this_timestamp(0), previous_timestamp(0);
|
||||||
|
difficulty_type L(0), next_D, avg_D;
|
||||||
|
|
||||||
|
previous_timestamp = timestamps[0]-T;
|
||||||
|
for ( i = 1; i <= N; i++) {
|
||||||
|
// Safely prevent out-of-sequence timestamps
|
||||||
|
if ( timestamps[i] > previous_timestamp ) { this_timestamp = timestamps[i]; }
|
||||||
|
else { this_timestamp = previous_timestamp+1; }
|
||||||
|
L += i*std::min(6*T ,this_timestamp - previous_timestamp);
|
||||||
|
previous_timestamp = this_timestamp;
|
||||||
|
}
|
||||||
|
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 && HEIGHT < 307800) {
|
||||||
|
next_D = (avg_D/(200*L))*(N*(N+1)*T*99);
|
||||||
|
}
|
||||||
|
else if (avg_D > uint64_t(-1)/(N*(N+1)*T*99) && HEIGHT > 307800) {
|
||||||
|
next_D = (avg_D/(200*L))*(N*(N+1)*T*99);
|
||||||
|
}
|
||||||
|
else { next_D = (avg_D*N*(N+1)*T*99)/(200*L); }
|
||||||
|
|
||||||
|
// 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; }
|
||||||
|
}
|
||||||
|
return next_D;
|
||||||
|
}
|
||||||
|
|
||||||
|
difficulty_type next_difficulty_v6(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
||||||
|
if(timestamps.size() > DIFFICULTY_WINDOW_V3)
|
||||||
|
{
|
||||||
|
timestamps.resize(DIFFICULTY_WINDOW_V3);
|
||||||
|
cumulative_difficulties.resize(DIFFICULTY_WINDOW_V3);
|
||||||
|
}
|
||||||
|
size_t length = timestamps.size();
|
||||||
|
assert(length == cumulative_difficulties.size());
|
||||||
|
if (length <= 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static_assert(DIFFICULTY_WINDOW_V3 >= 2, "Window is too small");
|
||||||
|
assert(length <= DIFFICULTY_WINDOW_V3);
|
||||||
|
sort(timestamps.begin(), timestamps.end());
|
||||||
|
size_t cut_begin, cut_end;
|
||||||
|
static_assert(2 * DIFFICULTY_CUT_V2 <= DIFFICULTY_WINDOW_V3 - 2, "Cut length is too large");
|
||||||
|
if (length <= DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) {
|
||||||
|
cut_begin = 0;
|
||||||
|
cut_end = length;
|
||||||
|
} else {
|
||||||
|
cut_begin = (length - (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) + 1) / 2;
|
||||||
|
cut_end = cut_begin + (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2);
|
||||||
|
}
|
||||||
|
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<difficulty_type>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,12 @@ namespace cryptonote
|
||||||
|
|
||||||
bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty);
|
bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty);
|
||||||
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
|
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
|
||||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
|
||||||
|
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
|
||||||
|
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
|
||||||
|
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
|
||||||
|
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
|
||||||
|
difficulty_type next_difficulty_v6(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||||
|
|
||||||
std::string hex(difficulty_type v);
|
std::string hex(difficulty_type v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,13 @@
|
||||||
#define DIFFICULTY_WINDOW_V3 144
|
#define DIFFICULTY_WINDOW_V3 144
|
||||||
#define DIFFICULTY_WINDOW_V2 60
|
#define DIFFICULTY_WINDOW_V2 60
|
||||||
#define DIFFICULTY_WINDOW 720 // blocks
|
#define DIFFICULTY_WINDOW 720 // blocks
|
||||||
|
#define DIFFICULTY_LAG_V2 3
|
||||||
#define DIFFICULTY_LAG 15 // !!!
|
#define DIFFICULTY_LAG 15 // !!!
|
||||||
|
#define DIFFICULTY_CUT_V2 12
|
||||||
#define DIFFICULTY_CUT 60 // timestamps to cut after sorting
|
#define DIFFICULTY_CUT 60 // timestamps to cut after sorting
|
||||||
|
#define DIFFICULTY_BLOCKS_COUNT_V4 DIFFICULTY_WINDOW_V3 + DIFFICULTY_LAG_V2
|
||||||
|
#define DIFFICULTY_BLOCKS_COUNT_V3 DIFFICULTY_WINDOW_V3 + 1
|
||||||
|
#define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + 1
|
||||||
#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG
|
#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -897,17 +897,19 @@ start:
|
||||||
// pop the oldest one from the list. This only requires 1x read per height instead
|
// pop the oldest one from the list. This only requires 1x read per height instead
|
||||||
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
|
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
|
||||||
bool check = false;
|
bool check = false;
|
||||||
|
uint8_t version = get_current_hard_fork_version();
|
||||||
|
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;
|
||||||
if (m_reset_timestamps_and_difficulties_height)
|
if (m_reset_timestamps_and_difficulties_height)
|
||||||
m_timestamps_and_difficulties_height = 0;
|
m_timestamps_and_difficulties_height = 0;
|
||||||
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= DIFFICULTY_BLOCKS_COUNT)
|
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficulty_blocks_count)
|
||||||
{
|
{
|
||||||
uint64_t index = height - 1;
|
uint64_t index = height - 1;
|
||||||
m_timestamps.push_back(m_db->get_block_timestamp(index));
|
m_timestamps.push_back(m_db->get_block_timestamp(index));
|
||||||
m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
|
m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
|
||||||
|
|
||||||
while (m_timestamps.size() > DIFFICULTY_BLOCKS_COUNT)
|
while (m_timestamps.size() > difficulty_blocks_count)
|
||||||
m_timestamps.erase(m_timestamps.begin());
|
m_timestamps.erase(m_timestamps.begin());
|
||||||
while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT)
|
while (m_difficulties.size() > difficulty_blocks_count)
|
||||||
m_difficulties.erase(m_difficulties.begin());
|
m_difficulties.erase(m_difficulties.begin());
|
||||||
|
|
||||||
m_timestamps_and_difficulties_height = height;
|
m_timestamps_and_difficulties_height = height;
|
||||||
|
@ -920,7 +922,7 @@ start:
|
||||||
std::vector<difficulty_type> difficulties_from_cache = difficulties;
|
std::vector<difficulty_type> difficulties_from_cache = difficulties;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(DIFFICULTY_BLOCKS_COUNT));
|
uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(difficulty_blocks_count));
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
++offset;
|
++offset;
|
||||||
|
|
||||||
|
@ -966,7 +968,21 @@ start:
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t target = get_difficulty_target();
|
size_t target = get_difficulty_target();
|
||||||
difficulty_type diff = next_difficulty(timestamps, difficulties, target);
|
uint64_t HEIGHT = m_db->height();
|
||||||
|
difficulty_type diff;
|
||||||
|
if (version >= 20) {
|
||||||
|
diff = next_difficulty_v6(timestamps, difficulties, target);
|
||||||
|
} else if (version <= 17 && version >= 11) {
|
||||||
|
diff = next_difficulty_v5(timestamps, difficulties, HEIGHT);
|
||||||
|
} else if (version == 10) {
|
||||||
|
diff = next_difficulty_v4(timestamps, difficulties, HEIGHT);
|
||||||
|
} else if (version == 9) {
|
||||||
|
diff = next_difficulty_v3(timestamps, difficulties, HEIGHT);
|
||||||
|
} else if (version == 8) {
|
||||||
|
diff = next_difficulty_v2(timestamps, difficulties, target, HEIGHT);
|
||||||
|
} else {
|
||||||
|
diff = next_difficulty(timestamps, difficulties, target, HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
CRITICAL_REGION_LOCAL1(m_difficulty_lock);
|
CRITICAL_REGION_LOCAL1(m_difficulty_lock);
|
||||||
m_difficulty_for_next_block_top_hash = top_hash;
|
m_difficulty_for_next_block_top_hash = top_hash;
|
||||||
|
@ -1025,11 +1041,13 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||||
|
|
||||||
std::vector<uint64_t> timestamps;
|
std::vector<uint64_t> timestamps;
|
||||||
std::vector<difficulty_type> difficulties;
|
std::vector<difficulty_type> difficulties;
|
||||||
timestamps.reserve(DIFFICULTY_BLOCKS_COUNT + 1);
|
uint8_t version = get_current_hard_fork_version();
|
||||||
difficulties.reserve(DIFFICULTY_BLOCKS_COUNT + 1);
|
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;
|
||||||
|
timestamps.reserve(difficulty_blocks_count + 1);
|
||||||
|
difficulties.reserve(difficulty_blocks_count + 1);
|
||||||
if (start_height > 1)
|
if (start_height > 1)
|
||||||
{
|
{
|
||||||
for (uint64_t i = 0; i < DIFFICULTY_BLOCKS_COUNT; ++i)
|
for (uint64_t i = 0; i < difficulty_blocks_count; ++i)
|
||||||
{
|
{
|
||||||
uint64_t height = start_height - 1 - i;
|
uint64_t height = start_height - 1 - i;
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
|
@ -1044,7 +1062,21 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||||
for (uint64_t height = start_height; height <= top_height; ++height)
|
for (uint64_t height = start_height; height <= top_height; ++height)
|
||||||
{
|
{
|
||||||
size_t target = get_ideal_hard_fork_version(height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
|
size_t target = get_ideal_hard_fork_version(height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
|
||||||
difficulty_type recalculated_diff = next_difficulty(timestamps, difficulties, target);
|
uint64_t HEIGHT = m_db->height();
|
||||||
|
difficulty_type recalculated_diff;
|
||||||
|
if (version >= 20) {
|
||||||
|
recalculated_diff = next_difficulty_v6(timestamps, difficulties, target);
|
||||||
|
} 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);
|
||||||
|
} else if (version == 9) {
|
||||||
|
recalculated_diff = next_difficulty_v3(timestamps, difficulties, HEIGHT);
|
||||||
|
} else if (version == 8) {
|
||||||
|
recalculated_diff = next_difficulty_v2(timestamps, difficulties, target, HEIGHT);
|
||||||
|
} else {
|
||||||
|
recalculated_diff = next_difficulty(timestamps, difficulties, target, HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
boost::multiprecision::uint256_t recalculated_cum_diff_256 = boost::multiprecision::uint256_t(recalculated_diff) + last_cum_diff;
|
boost::multiprecision::uint256_t recalculated_cum_diff_256 = boost::multiprecision::uint256_t(recalculated_diff) + last_cum_diff;
|
||||||
CHECK_AND_ASSERT_THROW_MES(recalculated_cum_diff_256 <= std::numeric_limits<difficulty_type>::max(), "Difficulty overflow!");
|
CHECK_AND_ASSERT_THROW_MES(recalculated_cum_diff_256 <= std::numeric_limits<difficulty_type>::max(), "Difficulty overflow!");
|
||||||
|
@ -1072,9 +1104,9 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||||
timestamps.push_back(m_db->get_block_timestamp(height));
|
timestamps.push_back(m_db->get_block_timestamp(height));
|
||||||
difficulties.push_back(recalculated_cum_diff);
|
difficulties.push_back(recalculated_cum_diff);
|
||||||
}
|
}
|
||||||
if (timestamps.size() > DIFFICULTY_BLOCKS_COUNT)
|
if (timestamps.size() > difficulty_blocks_count)
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(timestamps.size() == DIFFICULTY_BLOCKS_COUNT + 1, "Wrong timestamps size: " << timestamps.size());
|
CHECK_AND_ASSERT_THROW_MES(timestamps.size() == difficulty_blocks_count + 1, "Wrong timestamps size: " << timestamps.size());
|
||||||
timestamps.erase(timestamps.begin());
|
timestamps.erase(timestamps.begin());
|
||||||
difficulties.erase(difficulties.begin());
|
difficulties.erase(difficulties.begin());
|
||||||
}
|
}
|
||||||
|
@ -1299,16 +1331,18 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
std::vector<uint64_t> timestamps;
|
std::vector<uint64_t> timestamps;
|
||||||
std::vector<difficulty_type> cumulative_difficulties;
|
std::vector<difficulty_type> cumulative_difficulties;
|
||||||
|
uint8_t version = get_current_hard_fork_version();
|
||||||
|
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;
|
||||||
|
|
||||||
// if the alt chain isn't long enough to calculate the difficulty target
|
// if the alt chain isn't long enough to calculate the difficulty target
|
||||||
// based on its blocks alone, need to get more blocks from the main chain
|
// based on its blocks alone, need to get more blocks from the main chain
|
||||||
if(alt_chain.size()< DIFFICULTY_BLOCKS_COUNT)
|
if(alt_chain.size()< difficulty_blocks_count)
|
||||||
{
|
{
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||||
|
|
||||||
// Figure out start and stop offsets for main chain blocks
|
// Figure out start and stop offsets for main chain blocks
|
||||||
size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front().height : bei.height;
|
size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front().height : bei.height;
|
||||||
size_t main_chain_count = DIFFICULTY_BLOCKS_COUNT - std::min(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT), alt_chain.size());
|
size_t main_chain_count = difficulty_blocks_count - std::min(static_cast<size_t>(difficulty_blocks_count), alt_chain.size());
|
||||||
main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
|
main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
|
||||||
size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
|
size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
|
||||||
|
|
||||||
|
@ -1323,7 +1357,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?
|
// 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 (const auto &bei : alt_chain)
|
for (const auto &bei : alt_chain)
|
||||||
{
|
{
|
||||||
|
@ -1335,8 +1369,8 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||||
// and timestamps from it alone
|
// and timestamps from it alone
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timestamps.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
|
timestamps.resize(static_cast<size_t>(difficulty_blocks_count));
|
||||||
cumulative_difficulties.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
|
cumulative_difficulties.resize(static_cast<size_t>(difficulty_blocks_count));
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t max_i = timestamps.size()-1;
|
size_t max_i = timestamps.size()-1;
|
||||||
// get difficulties and timestamps from most recent blocks in alt chain
|
// get difficulties and timestamps from most recent blocks in alt chain
|
||||||
|
@ -1345,7 +1379,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||||
timestamps[max_i - count] = bei.bl.timestamp;
|
timestamps[max_i - count] = bei.bl.timestamp;
|
||||||
cumulative_difficulties[max_i - count] = bei.cumulative_difficulty;
|
cumulative_difficulties[max_i - count] = bei.cumulative_difficulty;
|
||||||
count++;
|
count++;
|
||||||
if(count >= DIFFICULTY_BLOCKS_COUNT)
|
if(count >= difficulty_blocks_count)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1354,7 +1388,22 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||||
size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
|
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
|
// calculate the difficulty target for the block and return it
|
||||||
return next_difficulty(timestamps, cumulative_difficulties, target);
|
uint64_t HEIGHT = m_db->height();
|
||||||
|
difficulty_type next_diff;
|
||||||
|
if (version >= 20) {
|
||||||
|
next_diff = next_difficulty_v6(timestamps, cumulative_difficulties, target);
|
||||||
|
} 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);
|
||||||
|
} else if (version == 9) {
|
||||||
|
next_diff = next_difficulty_v3(timestamps, cumulative_difficulties, HEIGHT);
|
||||||
|
} else if (version == 8) {
|
||||||
|
next_diff = next_difficulty_v2(timestamps, cumulative_difficulties, target, HEIGHT);
|
||||||
|
} else {
|
||||||
|
next_diff = next_difficulty(timestamps, cumulative_difficulties, target, HEIGHT);
|
||||||
|
}
|
||||||
|
return next_diff;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// This function does a sanity check on basic things that all miner
|
// This function does a sanity check on basic things that all miner
|
||||||
|
|
Loading…
Reference in New Issue