Faster difficulty algorithm

This commit is contained in:
_xxfedexx_ 2023-10-04 21:20:04 +02:00
parent 1b8475003c
commit 63aa55f6f2
4 changed files with 57 additions and 6 deletions

View file

@ -446,4 +446,41 @@ namespace cryptonote {
return 0; // to behave like previous implementation, may be better return max128bit?
return res.convert_to<difficulty_type>();
}
difficulty_type next_difficulty_v7(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
if(timestamps.size() > DIFFICULTY_WINDOW_V4)
{
timestamps.resize(DIFFICULTY_WINDOW_V4);
cumulative_difficulties.resize(DIFFICULTY_WINDOW_V4);
}
size_t length = timestamps.size();
assert(length == cumulative_difficulties.size());
if (length <= 1) {
return 1;
}
static_assert(DIFFICULTY_WINDOW_V4 >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW_V4);
// Timestamp sorting is not needed, since we don't cut
// sort(timestamps.begin(), timestamps.end());
size_t cut_begin, cut_end;
static_assert(2 * DIFFICULTY_CUT_V3 <= DIFFICULTY_WINDOW_V4 - 2, "Cut length is too large");
if (length <= DIFFICULTY_WINDOW_V4 - 2 * DIFFICULTY_CUT_V3) {
cut_begin = 0;
cut_end = length;
} else {
cut_begin = (length - (DIFFICULTY_WINDOW_V4 - 2 * DIFFICULTY_CUT_V3) + 1) / 2;
cut_end = cut_begin + (DIFFICULTY_WINDOW_V4 - 2 * DIFFICULTY_CUT_V3);
}
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>();
}
}

View file

@ -63,6 +63,7 @@ namespace cryptonote
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);
difficulty_type next_difficulty_v7(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
std::string hex(difficulty_type v);
}

View file

@ -81,13 +81,17 @@
#define DIFFICULTY_TARGET_V2 300 // seconds
#define DIFFICULTY_TARGET_V1 300 // seconds - before first fork
#define DIFFICULTY_WINDOW_V4 42 // 3 hours and half
#define DIFFICULTY_WINDOW_V3 144
#define DIFFICULTY_WINDOW_V2 60
#define DIFFICULTY_WINDOW 720 // blocks
#define DIFFICULTY_LAG_V3 0
#define DIFFICULTY_LAG_V2 3
#define DIFFICULTY_LAG 15 // !!!
#define DIFFICULTY_CUT_V3 0
#define DIFFICULTY_CUT_V2 12
#define DIFFICULTY_CUT 60 // timestamps to cut after sorting
#define DIFFICULTY_BLOCKS_COUNT_V5 DIFFICULTY_WINDOW_V4 + DIFFICULTY_LAG_V3
#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

View file

@ -898,7 +898,8 @@ start:
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
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;
uint64_t difficulty_blocks_count = version >= 21 ? DIFFICULTY_BLOCKS_COUNT_V5 :
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)
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)
@ -970,7 +971,9 @@ start:
size_t target = get_difficulty_target();
uint64_t HEIGHT = m_db->height();
difficulty_type diff;
if (version >= 20) {
if (version >= 21) {
diff = next_difficulty_v7(timestamps, difficulties, target);
} else if (version >= 20) {
diff = next_difficulty_v6(timestamps, difficulties, target);
} else if (version <= 17 && version >= 11) {
diff = next_difficulty_v5(timestamps, difficulties, HEIGHT);
@ -1042,7 +1045,8 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> 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;
uint64_t difficulty_blocks_count = version >= 21 ? DIFFICULTY_BLOCKS_COUNT_V5 :
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)
@ -1064,7 +1068,9 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
size_t target = get_ideal_hard_fork_version(height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
uint64_t HEIGHT = m_db->height();
difficulty_type recalculated_diff;
if (version >= 20) {
if (version >= 21) {
recalculated_diff = next_difficulty_v7(timestamps, difficulties, target);
} else 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);
@ -1332,7 +1338,8 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
std::vector<uint64_t> timestamps;
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;
uint64_t difficulty_blocks_count = version >= 21 ? DIFFICULTY_BLOCKS_COUNT_V5 :
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
// based on its blocks alone, need to get more blocks from the main chain
@ -1390,7 +1397,9 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// calculate the difficulty target for the block and return it
uint64_t HEIGHT = m_db->height();
difficulty_type next_diff;
if (version >= 20) {
if (version >= 21) {
next_diff = next_difficulty_v7(timestamps, cumulative_difficulties, target);
} else 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);