Merge pull request 'refactor diff' (#323) from wowario/wownero:diff into dev-v0.9
continuous-integration/drone/push Build is failing Details

Reviewed-on: #323
pull/325/head
jwinterm 4 years ago
commit 8fb16a3280

@ -182,6 +182,17 @@ namespace cryptonote
{ {
if (nettype == TESTNET) if (nettype == TESTNET)
{ {
ADD_CHECKPOINT2(1, "c47b8effcc84e22ddd1b876d059c8fbd3e26e4bdffb6bed8b8f4fe283104a7af", "0x2");
ADD_CHECKPOINT2(5, "292add330f6cf5f3845dc4cd2f28ce8d211dd487ddcfe1b5d1d545d7b90ff7d1", "0x5df"); //Hard fork to v8
ADD_CHECKPOINT2(10, "fbdf7d812aa6dd4c5915aadcbf023e722eab1d8ad47c24a230634e688d314798", "0xfa3"); //Hard fork to v9
ADD_CHECKPOINT2(15, "9b86e40b959d7cfe75366686dfd2657699e85b8c658aa8c20b23f7bc01b38af0", "0x1967"); //Hard fork to v10
ADD_CHECKPOINT2(20, "8f65c309ba3ed2bf25df2b7d91e1db40c864230aa3caaf823db81bc19e0bd6a3", "0x232b"); //Hard fork to v11
ADD_CHECKPOINT2(25, "35f2957fdba45d5421561ba2f126a61ec0101b5c2eb79b9e296310acbbdbbe58", "0x2cef"); //Hard fork to v12
ADD_CHECKPOINT2(30, "32cc5aacce8bea10ae869313e194ba51a30720810f3665433ffeea2818938429", "0x36b3"); //Hard fork to v13
ADD_CHECKPOINT2(35, "7f1cdd2c4a6002772343ad9de6c5dba743a0be1d326a6f63924511f08b15863a", "0x4077"); //Hard fork to v14
ADD_CHECKPOINT2(40, "63cf4f703489a881baf63bacd6a3af2b5bde79b558ce123e97313890be6f747f", "0x4a3b"); //Hard fork to v15
ADD_CHECKPOINT2(45, "65da4c966ae02983c6c8b7ab9b959df612863c379c5e48669061cbbb1e02a3ab", "0x53ff"); //Hard fork to v16
ADD_CHECKPOINT2(50, "8c68a444b6743a14152f130357be9751e42e82a84f69f25320eda532a830c7b0", "0x5dc3"); //Hard fork to v17
return true; return true;
} }
if (nettype == STAGENET) if (nettype == STAGENET)

@ -201,20 +201,19 @@ 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, network_type m_nettype, 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)
{ {
timestamps.resize(DIFFICULTY_WINDOW); timestamps.resize(DIFFICULTY_WINDOW);
cumulative_difficulties.resize(DIFFICULTY_WINDOW); cumulative_difficulties.resize(DIFFICULTY_WINDOW);
} }
size_t length = timestamps.size(); size_t length = timestamps.size();
assert(length == cumulative_difficulties.size()); assert(length == cumulative_difficulties.size());
if (length <= 1) { if (length <= 1) {
return 1; return 1;
} }
if (HEIGHT < 200 && HEIGHT > 2 && m_nettype == TESTNET) { return 500; }
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());
@ -258,18 +257,21 @@ namespace cryptonote {
// LWMA difficulty algorithm // LWMA difficulty algorithm
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3 // Background: https://github.com/zawy12/difficulty-algorithms/issues/3
// Copyright (c) 2017-2018 Zawy // Copyright (c) 2017-2018 Zawy
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) { difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
const int64_t T = static_cast<int64_t>(target_seconds); const int64_t T = static_cast<int64_t>(target_seconds);
size_t N = DIFFICULTY_WINDOW_V2; size_t N = DIFFICULTY_WINDOW_V2;
if (timestamps.size() < 4) { if (m_nettype == MAINNET) {
return 1; if (timestamps.size() < 4) {
} else if ( timestamps.size() < N+1 ) { return 1;
N = timestamps.size() - 1; } else if ( timestamps.size() < N+1 ) {
} else { N = timestamps.size() - 1;
timestamps.resize(N+1); } else {
cumulative_difficulties.resize(N+1); timestamps.resize(N+1);
cumulative_difficulties.resize(N+1);
}
} }
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
const double adjust = 0.998; const double adjust = 0.998;
const double k = N * (N + 1) / 2; const double k = N * (N + 1) / 2;
double LWMA(0), sum_inverse_D(0), harmonic_mean_D(0), nextDifficulty(0); double LWMA(0), sum_inverse_D(0), harmonic_mean_D(0), nextDifficulty(0);
@ -292,12 +294,13 @@ namespace cryptonote {
} }
// LWMA-2 // LWMA-2
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties) { difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
int64_t T = DIFFICULTY_TARGET_V2; int64_t T = DIFFICULTY_TARGET_V2;
int64_t N = DIFFICULTY_WINDOW_V2; int64_t N = DIFFICULTY_WINDOW_V2;
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D; 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) ); assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast<uint64_t>(N+1) );
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
for ( int64_t i = 1; i <= N; i++ ) { for ( int64_t i = 1; i <= N; i++ ) {
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]); ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]);
ST = std::max(-4*T, std::min(ST, 6*T)); ST = std::max(-4*T, std::min(ST, 6*T));
@ -316,13 +319,14 @@ namespace cryptonote {
} }
// LWMA-4 // LWMA-4
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t height) { difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
uint64_t T = DIFFICULTY_TARGET_V2; uint64_t T = DIFFICULTY_TARGET_V2;
uint64_t N = DIFFICULTY_WINDOW_V2; uint64_t N = DIFFICULTY_WINDOW_V2;
uint64_t L(0), ST(0), next_D, prev_D, avg_D, i; uint64_t L(0), ST(0), next_D, prev_D, avg_D, i;
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 ); assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if ( height <= 63469 + 1 ) { return 100000069; } if (HEIGHT <= 63469 + 1 && m_nettype == MAINNET) { return 100000069; }
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
std::vector<uint64_t>TS(N+1); std::vector<uint64_t>TS(N+1);
TS[0] = timestamps[0]; TS[0] = timestamps[0];
for ( i = 1; i <= N; i++) { for ( i = 1; i <= N; i++) {
@ -364,44 +368,11 @@ namespace cryptonote {
// LWMA-1 difficulty algorithm // LWMA-1 difficulty algorithm
// Copyright (c) 2017-2019 Zawy, MIT License // Copyright (c) 2017-2019 Zawy, MIT License
// https://github.com/zawy12/difficulty-algorithms/issues/3 // https://github.com/zawy12/difficulty-algorithms/issues/3
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT) { difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT) {
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if (HEIGHT >= 81769 && HEIGHT < 81769 + N) { return 10000000; }
assert(timestamps.size() == N+1);
uint64_t L(0), next_D, i, this_timestamp(0), previous_timestamp(0), 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 = static_cast<uint64_t>(( 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*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_test(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT) {
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 ); assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if (HEIGHT < N) { return 100; } if (HEIGHT >= 81769 && HEIGHT < 81769 + N && m_nettype == MAINNET) { return 10000000; }
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
assert(timestamps.size() == N+1); assert(timestamps.size() == N+1);
uint64_t L(0), next_D, i, this_timestamp(0), previous_timestamp(0), avg_D; uint64_t L(0), next_D, i, this_timestamp(0), previous_timestamp(0), avg_D;

@ -57,12 +57,11 @@ 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, network_type m_nettype, 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); difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, network_type m_nettype, 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); difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, network_type m_nettype, 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, size_t height); difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, network_type m_nettype, 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 T, uint64_t N, uint64_t HEIGHT); difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT);
difficulty_type next_difficulty_test(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT);
std::string hex(difficulty_type v); std::string hex(difficulty_type v);
} }

@ -946,37 +946,31 @@ start:
uint64_t N = DIFFICULTY_WINDOW_V3; uint64_t N = DIFFICULTY_WINDOW_V3;
uint64_t HEIGHT = m_db->height(); uint64_t HEIGHT = m_db->height();
difficulty_type diff = next_difficulty(timestamps, difficulties, target); difficulty_type diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
if (m_nettype == MAINNET) { if (version >= 11) {
if (version >= 11) { diff = next_difficulty_v5(timestamps, m_nettype, difficulties, T, N, HEIGHT);
diff = next_difficulty_v5(timestamps, difficulties, T, N, HEIGHT); } else if (version == 10) {
} else if (version == 10) { diff = next_difficulty_v4(timestamps, m_nettype, difficulties, HEIGHT);
diff = next_difficulty_v4(timestamps, difficulties, height); } else if (version == 9) {
} else if (version == 9) { diff = next_difficulty_v3(timestamps, m_nettype, difficulties, HEIGHT);
diff = next_difficulty_v3(timestamps, difficulties); } else if (version == 8) {
} else if (version == 8) { diff = next_difficulty_v2(timestamps, m_nettype, difficulties, target, HEIGHT);
diff = next_difficulty_v2(timestamps, difficulties, target); } else {
} else { diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
diff = next_difficulty(timestamps, difficulties, target);
}
}
if (m_nettype == TESTNET) {
diff = next_difficulty_test(timestamps, difficulties, T, N, 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;
m_difficulty_for_next_block = diff; m_difficulty_for_next_block = diff;
if (D && D != diff) if (D && D != diff && m_nettype == MAINNET)
{ {
ss << "XXX Mismatch at " << height << "/" << top_hash << "/" << get_tail_id() << ": cached " << D << ", real " << diff << std::endl; ss << "XXX Mismatch at " << height << "/" << top_hash << "/" << get_tail_id() << ": cached " << D << ", real " << diff << std::endl;
print = true; print = true;
} }
++done; ++done;
if (done == 1 && D && D != diff) if (done == 1 && D && D != diff && m_nettype == MAINNET)
{ {
print = true; print = true;
ss << "Might be a race. Let's see what happens if we try again..." << std::endl; ss << "Might be a race. Let's see what happens if we try again..." << std::endl;
@ -984,12 +978,12 @@ start:
goto start; goto start;
} }
ss << "Diff for " << top_hash << ": " << diff << std::endl; ss << "Diff for " << top_hash << ": " << diff << std::endl;
if (print) if (print && m_nettype == MAINNET)
{ {
MGINFO("START DUMP"); MGINFO("START DUMP");
MGINFO(ss.str()); MGINFO(ss.str());
MGINFO("END DUMP"); MGINFO("END DUMP");
MGINFO("Please send moneromooo on Freenode the contents of this log, from a couple dozen lines before START DUMP to END DUMP"); MGINFO("Please send wowario on Freenode #wownero-dev the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
} }
return diff; return diff;
} }
@ -1042,8 +1036,24 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
std::vector<difficulty_type> new_cumulative_difficulties; std::vector<difficulty_type> new_cumulative_difficulties;
for (uint64_t height = start_height; height <= top_height; ++height) for (uint64_t height = start_height; height <= top_height; ++height)
{ {
uint8_t version = get_current_hard_fork_version();
uint64_t T = DIFFICULTY_TARGET_V2;
uint64_t N = DIFFICULTY_WINDOW_V3;
uint64_t HEIGHT = m_db->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); difficulty_type recalculated_diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
if (version >= 11) {
recalculated_diff = next_difficulty_v5(timestamps, m_nettype, difficulties, T, N, HEIGHT);
} else if (version == 10) {
recalculated_diff = next_difficulty_v4(timestamps, m_nettype, difficulties, HEIGHT);
} else if (version == 9) {
recalculated_diff = next_difficulty_v3(timestamps, m_nettype, difficulties, HEIGHT);
} else if (version == 8) {
recalculated_diff = next_difficulty_v2(timestamps, m_nettype, difficulties, target, HEIGHT);
} else {
recalculated_diff = next_difficulty(timestamps, m_nettype, 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!");
@ -1347,24 +1357,18 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
uint64_t HEIGHT = m_db->height(); uint64_t HEIGHT = m_db->height();
// calculate the difficulty target for the block and return it // calculate the difficulty target for the block and return it
if (m_nettype == MAINNET) { if (version >= 11) {
if (version >= 11) { return next_difficulty_v5(timestamps, m_nettype, cumulative_difficulties, T, N, HEIGHT);
return next_difficulty_v5(timestamps, cumulative_difficulties, T, N, HEIGHT); } else if (version == 10) {
} else if (version == 10) { return next_difficulty_v4(timestamps, m_nettype, cumulative_difficulties, HEIGHT);
return next_difficulty_v4(timestamps, cumulative_difficulties, height); } else if (version == 9) {
} else if (version == 9) { return next_difficulty_v3(timestamps, m_nettype, cumulative_difficulties, HEIGHT);
return next_difficulty_v3(timestamps, cumulative_difficulties); } else if (version == 8) {
} else if (version == 8) { return next_difficulty_v2(timestamps, m_nettype, cumulative_difficulties, target, HEIGHT);
return next_difficulty_v2(timestamps, cumulative_difficulties, target); } else {
} else { return next_difficulty(timestamps, m_nettype, cumulative_difficulties, target, HEIGHT);
return next_difficulty(timestamps, cumulative_difficulties, target);
}
}
if (m_nettype == TESTNET) {
return next_difficulty_test(timestamps, cumulative_difficulties, T, N, HEIGHT);
} }
return next_difficulty(timestamps, cumulative_difficulties, target); return next_difficulty(timestamps, m_nettype, cumulative_difficulties, target, HEIGHT);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// 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…
Cancel
Save