Commit ded379a7 authored by contrem's avatar contrem

Merge remote-tracking branch 'origin/v16'

* origin/v16:
  DAA adjustments for v16.
  Increment version. (v1.0.3.6).
  Fix PoW in v16 hardfork.
parents 27289720 618a9ee7
......@@ -1229,6 +1229,8 @@ namespace cryptonote
{
switch (b.major_version)
{
case 16:
return get_block_longhash_v13(b, res, height, bc);
case 14:
return get_block_longhash_v13(b, res, height, bc);
case 13:
......
......@@ -126,12 +126,12 @@ namespace cryptonote {
return !carry;
}
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
difficulty_type next_difficulty_v1(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
if(timestamps.size() > DIFFICULTY_WINDOW)
if(timestamps.size() > DIFFICULTY_WINDOW_V1)
{
timestamps.resize(DIFFICULTY_WINDOW);
cumulative_difficulties.resize(DIFFICULTY_WINDOW);
timestamps.resize(DIFFICULTY_WINDOW_V1);
cumulative_difficulties.resize(DIFFICULTY_WINDOW_V1);
}
......@@ -140,17 +140,17 @@ namespace cryptonote {
if (length <= 1) {
return 1;
}
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW);
static_assert(DIFFICULTY_WINDOW_V1 >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW_V1);
sort(timestamps.begin(), timestamps.end());
size_t cut_begin, cut_end;
static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large");
if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) {
static_assert(2 * DIFFICULTY_CUT_V1 <= DIFFICULTY_WINDOW_V1 - 2, "Cut length is too large");
if (length <= DIFFICULTY_WINDOW_V1 - 2 * DIFFICULTY_CUT_V1) {
cut_begin = 0;
cut_end = length;
} else {
cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2;
cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT);
cut_begin = (length - (DIFFICULTY_WINDOW_V1 - 2 * DIFFICULTY_CUT_V1) + 1) / 2;
cut_end = cut_begin + (DIFFICULTY_WINDOW_V1 - 2 * DIFFICULTY_CUT_V1);
}
assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length);
uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin];
......@@ -264,7 +264,7 @@ namespace cryptonote {
t=T*N/2 if t < T*N/2 # in case of startup weirdness, keep t reasonable
next_D = d * k / t
*/
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, bool v4) {
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
if (timestamps.size() > DIFFICULTY_BLOCKS_COUNT_V3)
{
......@@ -281,45 +281,81 @@ namespace cryptonote {
uint64_t weighted_timespans = 0;
uint64_t target;
if (v4 == true) {
uint64_t previous_max = timestamps[0];
for (size_t i = 1; i < length; i++) {
uint64_t timespan;
uint64_t max_timestamp;
// adjust = 0.99 for N=60, leaving the + 1 for now as it's not affecting N
target = 99 * (((length + 1) / 2) * target_seconds) / 100;
for (size_t i = 1; i < length; i++) {
uint64_t timespan;
if (timestamps[i - 1] >= timestamps[i]) {
timespan = 1;
} else {
timespan = timestamps[i] - timestamps[i - 1];
}
if (timespan > 10 * target_seconds) {
timespan = 10 * target_seconds;
}
weighted_timespans += i * timespan;
}
target = ((length + 1) / 2) * target_seconds;
if (timestamps[i] > previous_max) {
max_timestamp = timestamps[i];
} else {
max_timestamp = previous_max;
}
uint64_t minimum_timespan = target_seconds * length / 2;
if (weighted_timespans < minimum_timespan) {
weighted_timespans = minimum_timespan;
}
timespan = max_timestamp - previous_max;
if (timespan == 0) {
timespan = 1;
} else if (timespan > 10 * target_seconds) {
timespan = 10 * target_seconds;
}
difficulty_type total_work = cumulative_difficulties.back() - cumulative_difficulties.front();
assert(total_work > 0);
weighted_timespans += i * timespan;
previous_max = max_timestamp;
uint64_t low, high;
mul(total_work, target, low, high);
if (high != 0) {
return 0;
}
if (low < weighted_timespans) {
return 1;
}
return low / weighted_timespans;
}
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
if (timestamps.size() > DIFFICULTY_BLOCKS_COUNT_V3)
{
timestamps.resize(DIFFICULTY_BLOCKS_COUNT_V3);
cumulative_difficulties.resize(DIFFICULTY_BLOCKS_COUNT_V3);
}
size_t length = timestamps.size();
assert(length == cumulative_difficulties.size());
if (length <= 1) {
return 1;
}
uint64_t weighted_timespans = 0;
uint64_t target;
uint64_t previous_max = timestamps[0];
for (size_t i = 1; i < length; i++) {
uint64_t timespan;
uint64_t max_timestamp;
if (timestamps[i] > previous_max) {
max_timestamp = timestamps[i];
} else {
max_timestamp = previous_max;
}
// adjust = 0.99 for N=60, leaving the + 1 for now as it's not affecting N
target = 99 * (((length + 1) / 2) * target_seconds) / 100;
} else {
for (size_t i = 1; i < length; i++) {
uint64_t timespan;
if (timestamps[i - 1] >= timestamps[i]) {
timespan = 1;
} else {
timespan = timestamps[i] - timestamps[i - 1];
}
if (timespan > 10 * target_seconds) {
timespan = 10 * target_seconds;
}
weighted_timespans += i * timespan;
timespan = max_timestamp - previous_max;
if (timespan == 0) {
timespan = 1;
} else if (timespan > 10 * target_seconds) {
timespan = 10 * target_seconds;
}
target = ((length + 1) / 2) * target_seconds;
weighted_timespans += i * timespan;
previous_max = max_timestamp;
}
// adjust = 0.99 for N=60, leaving the + 1 for now as it's not affecting N
target = 99 * (((length + 1) / 2) * target_seconds) / 100;
uint64_t minimum_timespan = target_seconds * length / 2;
if (weighted_timespans < minimum_timespan) {
......@@ -340,6 +376,7 @@ namespace cryptonote {
return low / weighted_timespans;
}
// LWMA difficulty algorithm
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3
// Copyright (c) 2017-2018 Zawy (pseudocode)
......@@ -366,6 +403,62 @@ namespace cryptonote {
// Cryptonote clones: #define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + 1
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
const int64_t T = static_cast<int64_t>(target_seconds);
size_t N = DIFFICULTY_WINDOW_V5;
int64_t FTL = static_cast<int64_t>(CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V6);
// Return a difficulty of 1 for first 3 blocks if it's the start of the chain.
if (timestamps.size() < 4) {
return 1;
}
// Otherwise, use a smaller N if the start of the chain is less than N+1.
else if ( timestamps.size() < N+1 ) {
N = timestamps.size() - 1;
}
// Otherwise make sure timestamps and cumulative_difficulties are correct size.
else {
timestamps.resize(N+1);
cumulative_difficulties.resize(N+1);
}
// To get an average solvetime to within +/- ~0.1%, use an adjustment factor.
// adjust=0.998 for N = 60
const double adjust = 0.998;
// The divisor k normalizes the LWMA sum to a standard LWMA.
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);
// Loop through N most recent blocks. N is most recently solved block.
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 * 10), std::max<int64_t>(solveTime, -FTL));
difficulty = 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;
// Limit LWMA same as Bitcoin's 1/4 in case something unforeseen occurs.
if (static_cast<int64_t>(boost::math::round(LWMA)) < T / 4)
LWMA = static_cast<double>(T / 4);
nextDifficulty = harmonic_mean_D * T / LWMA * adjust;
// No limits should be employed, but this is correct way to employ a 20% symmetrical limit:
// nextDifficulty=max(previous_Difficulty*0.8,min(previous_Difficulty/0.8, next_Difficulty));
next_difficulty = static_cast<uint64_t>(nextDifficulty);
if (next_difficulty == 0) {
return 1;
}
return next_difficulty;
}
difficulty_type next_difficulty_v6(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
const int64_t T = static_cast<int64_t>(target_seconds);
......
......@@ -54,8 +54,10 @@ namespace cryptonote
*/
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
difficulty_type next_difficulty_v1(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, 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);
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, bool v4);
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
difficulty_type next_difficulty_v6(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
}
......@@ -87,28 +87,27 @@
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD ((uint64_t)100000000) // 10 * pow(10,12)
#define DIFFICULTY_TARGET_V1 60 // seconds
#define DIFFICULTY_TARGET_V2 20 // seconds (after v16)
#define DIFFICULTY_WINDOW 720 // blocks
#define DIFFICULTY_LAG 15 // !!!
#define DIFFICULTY_CUT 60 // timestamps to cut after sorting
#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG
#define UNCLE_DIFFICULTY_TARGET DIFFICULTY_TARGET_V2/4
#define UNCLE_REWARD_RATIO 2
#define NEPHEW_REWARD_RATIO 20
#define UNCLE_MINING_FORK_HEIGHT 15
#define DIFFICULTY_TARGET_V2 20 // seconds (after v15)
#define DIFFICULTY_WINDOW_V1 720 // blocks
#define DIFFICULTY_LAG_V1 15 // !!!
#define DIFFICULTY_CUT_V1 60 // timestamps to cut after sorting
#define DIFFICULTY_BLOCKS_COUNT_V1 DIFFICULTY_WINDOW_V1 + DIFFICULTY_LAG_V1
#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN DIFFICULTY_TARGET_V1 //just alias; used by tests
#define DIFFICULTY_WINDOW_V2 17
#define DIFFICULTY_CUT_V2 6
#define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + DIFFICULTY_CUT_V2*2
#define DIFFICULTY_WINDOW_V3 60
#define DIFFICULTY_BLOCKS_COUNT_V3 DIFFICULTY_WINDOW_V3
#define DIFFICULTY_WINDOW_V6 60
#define DIFFICULTY_WINDOW_V5 60
#define DIFFICULTY_BLOCKS_COUNT_V5 DIFFICULTY_WINDOW_V5 + 1
#define DIFFICULTY_WINDOW_V6 180
#define DIFFICULTY_BLOCKS_COUNT_V6 DIFFICULTY_WINDOW_V6 + 1
#define UNCLE_DIFFICULTY_TARGET DIFFICULTY_TARGET_V2 / 4
#define UNCLE_REWARD_RATIO 2
#define NEPHEW_REWARD_RATIO 20
#define UNCLE_MINING_FORK_HEIGHT 15
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 DIFFICULTY_TARGET_V1 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2 DIFFICULTY_TARGET_V2 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS 1
......
......@@ -106,6 +106,7 @@ static const struct {
{ 13, 81001, 0, 1546179019 },
{ 14, 88001, 0, 1546602163 },
{ 15, 227001, 0, 1554902709 },
{ 16, 277001, 0, 1555950611 },
};
static const struct {
......@@ -129,8 +130,7 @@ static const struct {
{ 13, 160, 0, 1546396236 },
{ 14, 170, 0, 1546602163 },
{ 15, 180, 0, 1546701111 },
{ 16, 1460, 0, 1546801111 },
{ 17, 5300, 0, 1546901111 },
{ 16, 190, 0, 1546801111 },
};
static const struct {
......@@ -989,11 +989,13 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
size_t difficulty_blocks_count;
uint8_t version = get_current_hard_fork_version();
if (version == 1) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT;
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V1;
} else if (version == 2) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V2;
} else if (version < 6) {
} else if (version >= 3 && version <= 5 ) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V3;
} else if (version >= 6 && version <= 15) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V5;
} else {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V6;
}
......@@ -1038,13 +1040,15 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
}
size_t target = get_current_hard_fork_version() < BLOCK_TARGET_FORK_HEIGHT ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
if (version == 1) {
return next_difficulty(timestamps, difficulties, target);
return next_difficulty_v1(timestamps, difficulties, target);
} else if (version == 2) {
return next_difficulty_v2(timestamps, difficulties, target);
} else if (version == 3) {
return next_difficulty_v3(timestamps, difficulties, target, false);
} else if (version < 6) {
return next_difficulty_v3(timestamps, difficulties, target, true);
return next_difficulty_v3(timestamps, difficulties, target);
} else if (version >= 3 && version <= 5) {
return next_difficulty_v4(timestamps, difficulties, target);
} else if (version >= 6 && version <= 15) {
return next_difficulty_v5(timestamps, difficulties, target);
} else {
return next_difficulty_v6(timestamps, difficulties, target);
}
......@@ -1226,11 +1230,13 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
size_t difficulty_blocks_count;
uint8_t version = get_current_hard_fork_version();
if (version == 1) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT;
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V1;
} else if (version == 2) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V2;
} else if (version < 6) {
} else if (version >= 3 && version <= 5) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V3;
} else if (version >= 6 && version <= 15) {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V5;
} else {
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V6;
}
......@@ -1290,13 +1296,15 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// calculate the difficulty target for the block and return it
if (version == 1) {
return next_difficulty(timestamps, cumulative_difficulties, target);
return next_difficulty_v1(timestamps, cumulative_difficulties, target);
} else if (version == 2) {
return next_difficulty_v2(timestamps, cumulative_difficulties, target);
} else if (version == 3) {
return next_difficulty_v3(timestamps, cumulative_difficulties, target, false);
} else if (version < 6) {
return next_difficulty_v3(timestamps, cumulative_difficulties, target, true);
return next_difficulty_v3(timestamps, cumulative_difficulties, target);
} else if (version == 4 || version == 5) {
return next_difficulty_v4(timestamps, cumulative_difficulties, target);
} else if (version >= 6 && version <= 15) {
return next_difficulty_v5(timestamps, cumulative_difficulties, target);
} else {
return next_difficulty_v6(timestamps, cumulative_difficulties, target);
}
......
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "1.0.3.5"
#define DEF_MONERO_VERSION "1.0.3.6"
#define DEF_MONERO_RELEASE_NAME "Han"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment