New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge hard fork 3 changes into master #94

Merged
merged 41 commits into from Jan 5, 2019
Commits
File filter...
Filter file types
Jump to file or symbol
Failed to load files and symbols.
+149 −10
Diff settings

Always

Just for now

Adjust difficulty calculation

  • Loading branch information...
atanmarko committed Jan 3, 2019
commit cc445b889a809b9b3234bf40211d634a0ef05763
@@ -178,5 +178,95 @@ difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vect
#endif
}

/*
# Tom Harold (Degnr8) WT
# Modified by Zawy to be a weighted-Weighted Harmonic Mean (WWHM)
# Copyright (c) 2017-2018 Zawy https://github.com/zawy12/difficulty-algorithms/issues/3
# Copyright (c) 2017-2018 The Masari Project
# No limits in rise or fall rate should be employed.
# MTP should not be used.
k = (N+1)/2 * T
# original algorithm
d=0, t=0, j=0
for i = height - N+1 to height # (N most recent blocks)
# TS = timestamp
solvetime = TS[i] - TS[i-1]
solvetime = 10*T if solvetime > 10*T
solvetime = -9*T if solvetime < -9*T
j++
t += solvetime * j
d +=D[i] # sum the difficulties
next i
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_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds)
{

if (timestamps.size() > DIFFICULTY_BLOCKS_COUNT_V2)
{
timestamps.resize(DIFFICULTY_BLOCKS_COUNT_V2);
cumulative_difficulties.resize(DIFFICULTY_BLOCKS_COUNT_V2);
}

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

timespan = max_timestamp - previous_max;
if (timespan == 0)
{
timespan = 1;
} else if (timespan > 10 * target_seconds)
{
// The below check is only needed for higher FTL's
timespan = 10 * target_seconds;
}

weighted_timespans += i * timespan;
previous_max = max_timestamp;
}

target = 9909 * (((length) / 2) * target_seconds) / 10000;

uint64_t minimum_timespan = target_seconds * length / 2;
if (weighted_timespans < minimum_timespan)
{
weighted_timespans = minimum_timespan;
}

difficulty_type total_work = cumulative_difficulties.back() - cumulative_difficulties.front();
assert(total_work > 0);

uint64_t low, high;
mul(total_work, target, low, high);
if (high != 0)
{
return 0;
}
return low / weighted_timespans;
}


}
@@ -54,4 +54,5 @@ namespace cryptonote
*/
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_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
}
Copy path View file
@@ -50,6 +50,9 @@

#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60

#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 500
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 12

// COIN - number of smallest units in one coin
#define COIN ((uint64_t)10000000000) // pow(10, 10)
#define SAFEX_CASH_COIN COIN
@@ -85,6 +88,11 @@
#define DIFFICULTY_CUT 60 // timestamps to cut after sorting
#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG

#define DIFFICULTY_WINDOW_V2 60
#define DIFFICULTY_LAG_V2 0 // just for refrence
#define DIFFICULTY_CUT_V2 0 // just for refrence
#define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2

#define DIFFICULTY_SECONDS_PER_YEAR ((uint64_t)31557600)
#define DIFFICULTY_BLOCKS_PER_YEAR ((uint64_t)DIFFICULTY_SECONDS_PER_YEAR/DIFFICULTY_TARGET)

@@ -147,6 +155,7 @@
#define HF_VERSION_ENFORCE_RCT HF_VERSION_TBD //enforce RingCT transactions
#define HF_VERSION_FORBID_DUST HF_VERSION_TBD //forbid dust and compound outputs
#define HF_VERSION_ALLOW_BULLETPROOFS HF_VERSION_TBD
#define HF_VERSION_DIFFICULTY_V2 3

#define DEFAULT_MIX 6 //default wallet mix for transactions

@@ -781,20 +781,32 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties;
auto height = m_db->height();
size_t difficulty_blocks_count;

if (m_hardfork->get_current_version() < HF_VERSION_DIFFICULTY_V2)
{
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT;
}
else
{
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V2;
}


// ND: Speedup
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
// then when the next block difficulty is queried, push the latest height data and
// pop the oldest one from the list. This only requires 1x read per height instead
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1))
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;
m_timestamps.push_back(m_db->get_block_timestamp(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());
while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT)
while (m_difficulties.size() > difficulty_blocks_count)
m_difficulties.erase(m_difficulties.begin());

m_timestamps_and_difficulties_height = height;
@@ -803,7 +815,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
}
else
{
size_t offset = height - std::min < size_t > (height, static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
size_t offset = height - std::min < size_t > (height, static_cast<size_t>(difficulty_blocks_count));
if (offset == 0)
++offset;

@@ -820,7 +832,16 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
m_difficulties = difficulties;
}
size_t target = get_difficulty_target();
return next_difficulty(timestamps, difficulties, target);

if (m_hardfork->get_current_version() < HF_VERSION_DIFFICULTY_V2)
{
return next_difficulty(timestamps, difficulties, target);
}
else
{
return next_difficulty_v2(timestamps, difficulties, target);
}

}
//------------------------------------------------------------------
// This function removes blocks from the blockchain until it gets to the
@@ -3303,10 +3324,17 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
{
LOG_PRINT_L3("Blockchain::" << __func__);
uint64_t median_ts = epee::misc_utils::median(timestamps);
size_t blockchain_timestamp_check_window;

if (m_hardfork->get_current_version() < HF_VERSION_DIFFICULTY_V2) {
blockchain_timestamp_check_window = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
} else {
blockchain_timestamp_check_window = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2;
}

if(b.timestamp < median_ts)
{
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << blockchain_timestamp_check_window << " blocks, " << median_ts);
return false;
}

@@ -3323,14 +3351,25 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
bool Blockchain::check_block_timestamp(const block& b) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
if(b.timestamp > get_adjusted_time() + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT)
uint64_t cryptonote_block_future_time_limit;
size_t blockchain_timestamp_check_window;

if (m_hardfork->get_current_version() < HF_VERSION_DIFFICULTY_V2) {
cryptonote_block_future_time_limit = CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT;
blockchain_timestamp_check_window = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
} else {
cryptonote_block_future_time_limit = CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2;
blockchain_timestamp_check_window = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2;
}

if(b.timestamp > get_adjusted_time() + cryptonote_block_future_time_limit)
{
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours");
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + " << (m_hardfork->get_current_version() < HF_VERSION_DIFFICULTY_V2 ? "2 hours" : "30 minutes"));
return false;
}

// if not enough blocks, no proper median yet, return true
if(m_db->height() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
if(m_db->height() < blockchain_timestamp_check_window)
{
return true;
}
@@ -3339,7 +3378,7 @@ bool Blockchain::check_block_timestamp(const block& b) const
auto h = m_db->height();

// need most recent 60 blocks, get index of first of those
size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
size_t offset = h - blockchain_timestamp_check_window;
for(;offset < h; ++offset)
{
timestamps.push_back(m_db->get_block_timestamp(offset));
ProTip! Use n and p to navigate between commits in a pull request.