|
|
|
@ -102,7 +102,8 @@ static const struct {
|
|
|
|
|
time_t time;
|
|
|
|
|
} testnet_hard_forks[] = {
|
|
|
|
|
//{ 1, 1, 0, 1341378000 },
|
|
|
|
|
{ 7, 1, 0, 1519605000 }
|
|
|
|
|
{ 7, 1, 0, 1519605000 },
|
|
|
|
|
{ 8, 10, 0, 1523255371 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)(1));
|
|
|
|
@ -727,20 +728,29 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
|
|
|
|
|
std::vector<uint64_t> timestamps;
|
|
|
|
|
std::vector<difficulty_type> difficulties;
|
|
|
|
|
auto height = m_db->height();
|
|
|
|
|
|
|
|
|
|
uint8_t version = get_current_hard_fork_version();
|
|
|
|
|
size_t difficulty_blocks_count;
|
|
|
|
|
if (version == 7) {
|
|
|
|
|
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;
|
|
|
|
@ -749,7 +759,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;
|
|
|
|
|
|
|
|
|
@ -765,8 +775,12 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
|
|
|
|
|
m_timestamps = timestamps;
|
|
|
|
|
m_difficulties = difficulties;
|
|
|
|
|
}
|
|
|
|
|
size_t target = get_difficulty_target();
|
|
|
|
|
size_t target = DIFFICULTY_TARGET_V2;
|
|
|
|
|
if (version == 7) {
|
|
|
|
|
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
|
|
|
|
@ -914,16 +928,23 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
|
|
|
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
|
|
|
|
std::vector<uint64_t> timestamps;
|
|
|
|
|
std::vector<difficulty_type> cumulative_difficulties;
|
|
|
|
|
uint8_t version = get_current_hard_fork_version();
|
|
|
|
|
size_t difficulty_blocks_count;
|
|
|
|
|
if (version == 7) {
|
|
|
|
|
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT;
|
|
|
|
|
} else {
|
|
|
|
|
difficulty_blocks_count = DIFFICULTY_BLOCKS_COUNT_V2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
if(alt_chain.size()< DIFFICULTY_BLOCKS_COUNT)
|
|
|
|
|
if(alt_chain.size()< difficulty_blocks_count)
|
|
|
|
|
{
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
|
|
|
|
|
|
|
|
|
// Figure out start and stop offsets for main chain blocks
|
|
|
|
|
size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.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);
|
|
|
|
|
size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
|
|
|
|
|
|
|
|
|
@ -938,7 +959,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?
|
|
|
|
|
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 (auto it : alt_chain)
|
|
|
|
|
{
|
|
|
|
@ -950,8 +971,8 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
|
|
|
|
// and timestamps from it alone
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
timestamps.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
|
|
|
|
|
cumulative_difficulties.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));
|
|
|
|
|
size_t count = 0;
|
|
|
|
|
size_t max_i = timestamps.size()-1;
|
|
|
|
|
// get difficulties and timestamps from most recent blocks in alt chain
|
|
|
|
@ -960,7 +981,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
|
|
|
|
timestamps[max_i - count] = it->second.bl.timestamp;
|
|
|
|
|
cumulative_difficulties[max_i - count] = it->second.cumulative_difficulty;
|
|
|
|
|
count++;
|
|
|
|
|
if(count >= DIFFICULTY_BLOCKS_COUNT)
|
|
|
|
|
if(count >= difficulty_blocks_count)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -969,8 +990,13 @@ 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;
|
|
|
|
|
|
|
|
|
|
// calculate the difficulty target for the block and return it
|
|
|
|
|
if (version == 7) {
|
|
|
|
|
return next_difficulty(timestamps, cumulative_difficulties, target);
|
|
|
|
|
} else {
|
|
|
|
|
return next_difficulty_v2(timestamps, cumulative_difficulties, target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
// This function does a sanity check on basic things that all miner
|
|
|
|
|
// transactions have in common, such as:
|
|
|
|
@ -3123,7 +3149,8 @@ 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 = get_current_hard_fork_version() < 7 ? CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT : CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_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");
|
|
|
|
|
return false;
|
|
|
|
|