diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp index 2b5466791..a2f7a794c 100644 --- a/src/cryptonote_core/difficulty.cpp +++ b/src/cryptonote_core/difficulty.cpp @@ -116,8 +116,8 @@ namespace cryptonote { return !carry; } - difficulty_type next_difficulty(vector timestamps, vector cumulative_difficulties, size_t target_seconds) { - //cutoff DIFFICULTY_LAG + difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds) { + if(timestamps.size() > DIFFICULTY_WINDOW) { timestamps.resize(DIFFICULTY_WINDOW); @@ -151,13 +151,15 @@ namespace cryptonote { assert(total_work > 0); uint64_t low, high; mul(total_work, target_seconds, low, high); + // blockchain errors "difficulty overhead" if this function returns zero. + // TODO: consider throwing an exception instead if (high != 0 || low + time_span - 1 < low) { return 0; } return (low + time_span - 1) / time_span; } - difficulty_type next_difficulty(vector timestamps, vector cumulative_difficulties) + difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties) { return next_difficulty(std::move(timestamps), std::move(cumulative_difficulties), DIFFICULTY_TARGET); } diff --git a/src/cryptonote_core/difficulty.h b/src/cryptonote_core/difficulty.h index 42d2df500..d1b36ed9b 100644 --- a/src/cryptonote_core/difficulty.h +++ b/src/cryptonote_core/difficulty.h @@ -39,7 +39,44 @@ namespace cryptonote { typedef std::uint64_t difficulty_type; + /** + * @brief checks if a hash fits the given difficulty + * + * The hash passes if (hash * difficulty) < 2^192. + * Phrased differently, if (hash * difficulty) fits without overflow into + * the least significant 192 bits of the 256 bit multiplication result. + * + * @param hash the hash to check + * @param difficulty the difficulty to check against + * + * @return true if valid, else false + */ bool check_hash(const crypto::hash &hash, difficulty_type difficulty); + + /** + * @brief gets the required difficulty for the next block + * + * This function calculates the required difficulty for the block that + * follows the blocks to which the passed timestamps and difficulties + * belong. + * + * The current difficulty algorithm is as follows: + * - take the total time and cumulative difficulty ("total work") + * - let m = the total work multiplied by the target block time + * - if (m + total time) > 2^64, give 0 for the next difficulty, + * the blockchain class treats this as an error "difficulty overhead" + * + * - the next difficulty = (m + the total time - 1) / the total time + * + * @param timestamps the most recent timestamps + * @param cumulative_difficulties the most recent difficulties + * + * @return the required difficulty for the next block + */ difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties); + + /** + * @overload + */ difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds); }