diff --git a/include/BlockchainExplorerData.h b/include/BlockchainExplorerData.h index 135b44c3de..17d9b6a511 100644 --- a/include/BlockchainExplorerData.h +++ b/include/BlockchainExplorerData.h @@ -21,11 +21,12 @@ #include #include #include +#include #include "CryptoTypes.h" #include "CryptoNote.h" +#include "CryptoNoteCore/Difficulty.h" #include "BlockchainExplorerData.h" -#include namespace CryptoNote { @@ -154,7 +155,7 @@ struct BlockDetails { uint32_t depth = 0; Crypto::Hash hash; uint64_t difficulty = 0; - uint64_t cumulativeDifficulty = 0; + CryptoNote::Difficulty cumulativeDifficulty; uint64_t reward = 0; uint64_t baseReward = 0; uint64_t blockSize = 0; diff --git a/include/INode.h b/include/INode.h index 9cf51ce58c..e10d733935 100644 --- a/include/INode.h +++ b/include/INode.h @@ -77,7 +77,7 @@ struct BlockHeaderInfo { uint32_t nonce; bool isAlternative; uint32_t depth; // last block index = current block index + depth - difficulty_type difficulty; + uint64_t difficulty; uint64_t reward; }; diff --git a/src/CryptoNoteCore/Blockchain.cpp b/src/CryptoNoteCore/Blockchain.cpp index c8109e7787..388c6300b2 100644 --- a/src/CryptoNoteCore/Blockchain.cpp +++ b/src/CryptoNoteCore/Blockchain.cpp @@ -731,14 +731,14 @@ bool Blockchain::getTransactionHeight(const Crypto::Hash &txId, uint32_t& blockH return false; } -difficulty_type Blockchain::getDifficultyForNextBlock(const Crypto::Hash &prevHash) { +Difficulty Blockchain::getDifficultyForNextBlock(const Crypto::Hash &prevHash) { if (prevHash == NULL_HASH) { return 1; } std::lock_guard lk(m_blockchain_lock); std::vector timestamps; - std::vector cumulative_difficulties; + std::vector cumulative_difficulties; uint32_t height = static_cast(m_blocks.size()); uint8_t BlockMajorVersion = getBlockMajorVersionForHeight(height); @@ -1176,13 +1176,13 @@ bool Blockchain::getHashingBlob(const uint32_t height, BinaryArray& blob) { return true; } -bool Blockchain::checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) { +bool Blockchain::checkProofOfWork(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) { std::list dummy_alt_chain; return checkProofOfWork(context, block, currentDiffic, proofOfWork, dummy_alt_chain, m_no_blobs); } -bool Blockchain::checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork, const std::list& alt_chain, bool no_blobs) { +bool Blockchain::checkProofOfWork(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork, const std::list& alt_chain, bool no_blobs) { if (block.majorVersion < CryptoNote::BLOCK_MAJOR_VERSION_5) return m_currency.checkProofOfWork(context, block, currentDiffic, proofOfWork); @@ -1398,7 +1398,7 @@ bool Blockchain::handle_alternative_block(const Block& b, const Crypto::Hash& id } // Check the block's hash against the difficulty target for its alt chain - difficulty_type current_diff = getDifficultyForNextBlock(bei.bl.previousBlockHash); + Difficulty current_diff = getDifficultyForNextBlock(bei.bl.previousBlockHash); if (!current_diff) { logger(ERROR, BRIGHT_RED) << "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"; return false; @@ -1688,24 +1688,24 @@ uint64_t Blockchain::blockDifficulty(size_t i) { std::lock_guard lk(m_blockchain_lock); if (!(i < m_blocks.size())) { logger(ERROR, BRIGHT_RED) << "wrong block index i = " << i << " at Blockchain::block_difficulty()"; return false; } if (i == 0) - return m_blocks[i].cumulative_difficulty; + return m_blocks[i].cumulative_difficulty.convert_to(); - return m_blocks[i].cumulative_difficulty - m_blocks[i - 1].cumulative_difficulty; + return (m_blocks[i].cumulative_difficulty - m_blocks[i - 1].cumulative_difficulty).convert_to(); } -uint64_t Blockchain::blockCumulativeDifficulty(size_t i) { +Difficulty Blockchain::blockCumulativeDifficulty(size_t i) { std::lock_guard lk(m_blockchain_lock); if (!(i < m_blocks.size())) { logger(ERROR, BRIGHT_RED) << "wrong block index i = " << i << " at Blockchain::block_difficulty()"; return false; } return m_blocks[i].cumulative_difficulty; } -bool Blockchain::getblockEntry(size_t i, uint64_t& block_cumulative_size, difficulty_type& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) { +bool Blockchain::getblockEntry(size_t i, uint64_t& block_cumulative_size, uint64_t& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) { std::lock_guard lk(m_blockchain_lock); if (!(i < m_blocks.size())) { logger(ERROR, BRIGHT_RED) << "wrong block index i = " << i << " at Blockchain::get_block_entry()"; return false; } block_cumulative_size = m_blocks[i].block_cumulative_size; - difficulty = m_blocks[i].cumulative_difficulty - m_blocks[i - 1].cumulative_difficulty; + difficulty = (m_blocks[i].cumulative_difficulty - m_blocks[i - 1].cumulative_difficulty).convert_to(); already_generated_coins = m_blocks[i].already_generated_coins; reward = m_blocks[i].already_generated_coins - m_blocks[i - 1].already_generated_coins; timestamp = m_blocks[i].bl.timestamp; @@ -2247,7 +2247,7 @@ bool Blockchain::pushBlock(const Block& blockData, const std::vector(std::chrono::steady_clock::now() - targetTimeStart).count(); if (!(currentDifficulty)) { diff --git a/src/CryptoNoteCore/Blockchain.h b/src/CryptoNoteCore/Blockchain.h index f82c4a2c66..03d05e1415 100755 --- a/src/CryptoNoteCore/Blockchain.h +++ b/src/CryptoNoteCore/Blockchain.h @@ -93,7 +93,7 @@ namespace CryptoNote { uint32_t getCurrentBlockchainHeight(); //TODO rename to getCurrentBlockchainSize Crypto::Hash getTailId(); Crypto::Hash getTailId(uint32_t& height); - difficulty_type getDifficultyForNextBlock(const Crypto::Hash &prevHash); + Difficulty getDifficultyForNextBlock(const Crypto::Hash &prevHash); uint64_t getBlockTimestamp(uint32_t height); uint64_t getCoinsInCirculation(); uint64_t getCoinsInCirculation(uint32_t height); @@ -115,8 +115,8 @@ namespace CryptoNote { bool checkTransactionInputs(const Transaction& tx, uint32_t& pmax_used_block_height, Crypto::Hash& max_used_block_id, BlockInfo* tail = 0); uint64_t getCurrentCumulativeBlocksizeLimit(); uint64_t blockDifficulty(size_t i); - uint64_t blockCumulativeDifficulty(size_t i); - bool getblockEntry(size_t i, uint64_t& block_cumulative_size, difficulty_type& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp); + Difficulty blockCumulativeDifficulty(size_t i); + bool getblockEntry(size_t i, uint64_t& block_cumulative_size, uint64_t& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp); bool getBlockContainingTransaction(const Crypto::Hash& txId, Crypto::Hash& blockId, uint32_t& blockHeight); bool getAlreadyGeneratedCoins(const Crypto::Hash& hash, uint64_t& generatedCoins); bool getBlockSize(const Crypto::Hash& hash, size_t& size); @@ -212,7 +212,7 @@ namespace CryptoNote { void rebuildCache(); bool storeCache(); - bool checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork); + bool checkProofOfWork(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork); bool getBlockLongHash(Crypto::cn_context &context, const Block& b, Crypto::Hash& res); private: @@ -243,7 +243,7 @@ namespace CryptoNote { Block bl; uint32_t height; uint64_t block_cumulative_size; - difficulty_type cumulative_difficulty; + Difficulty cumulative_difficulty; uint64_t already_generated_coins; std::vector transactions; @@ -312,7 +312,7 @@ namespace CryptoNote { bool switch_to_alternative_blockchain(const std::list& alt_chain, bool discard_disconnected_chain); bool handle_alternative_block(const Block& b, const Crypto::Hash& id, block_verification_context& bvc, bool sendNewAlternativeBlockMessage = true); - bool checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork, const std::list& alt_chain, bool no_blobs = false); + bool checkProofOfWork(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork, const std::list& alt_chain, bool no_blobs = false); bool getBlockLongHash(Crypto::cn_context& context, const Block& b, Crypto::Hash& res, const std::list& alt_chain, bool no_blobs = false); bool prevalidate_miner_transaction(const Block& b, uint32_t height); bool validate_miner_transaction(const Block& b, uint32_t height, size_t cumulativeBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, uint64_t& reward, int64_t& emissionChange); diff --git a/src/CryptoNoteCore/Core.cpp b/src/CryptoNoteCore/Core.cpp index eb20caf2b9..add13bafc0 100755 --- a/src/CryptoNoteCore/Core.cpp +++ b/src/CryptoNoteCore/Core.cpp @@ -168,7 +168,7 @@ size_t Core::getAlternativeBlocksCount() { return m_blockchain.getAlternativeBlocksCount(); } -bool Core::getblockEntry(uint32_t height, uint64_t& block_cumulative_size, difficulty_type& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) { +bool Core::getblockEntry(uint32_t height, uint64_t& block_cumulative_size, uint64_t& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) { return m_blockchain.getblockEntry(static_cast(height), block_cumulative_size, difficulty, already_generated_coins, reward, transactions_count, timestamp); } @@ -501,7 +501,7 @@ bool Core::add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, keeped_by_block); } -bool Core::get_block_template(Block& b, const AccountKeys& acc, difficulty_type& diffic, uint32_t& height, const BinaryArray& ex_nonce) { +bool Core::get_block_template(Block& b, const AccountKeys& acc, Difficulty& diffic, uint32_t& height, const BinaryArray& ex_nonce) { size_t median_size; uint64_t already_generated_coins; @@ -1098,12 +1098,12 @@ bool Core::getBlockTimestamp(uint32_t height, uint64_t& timestamp) { return true; } -bool Core::getBlockDifficulty(uint32_t height, difficulty_type& difficulty) { +bool Core::getBlockDifficulty(uint32_t height, uint64_t& difficulty) { difficulty = m_blockchain.blockDifficulty(height); return true; } -bool Core::getBlockCumulativeDifficulty(uint32_t height, difficulty_type& difficulty) { +bool Core::getBlockCumulativeDifficulty(uint32_t height, Difficulty& difficulty) { difficulty = m_blockchain.blockCumulativeDifficulty(height); return true; } @@ -1225,7 +1225,7 @@ std::error_code Core::executeLocked(const std::function& func } uint64_t Core::getNextBlockDifficulty() { - return m_blockchain.getDifficultyForNextBlock(get_tail_id()); + return m_blockchain.getDifficultyForNextBlock(get_tail_id()).convert_to(); } uint64_t Core::getTotalGeneratedAmount() { diff --git a/src/CryptoNoteCore/Core.h b/src/CryptoNoteCore/Core.h index a96e3b83b2..c0df1cf00c 100755 --- a/src/CryptoNoteCore/Core.h +++ b/src/CryptoNoteCore/Core.h @@ -58,7 +58,7 @@ namespace CryptoNote { //-------------------- IMinerHandler ----------------------- virtual bool handle_block_found(Block& b) override; - virtual bool get_block_template(Block& b, const AccountKeys& acc, difficulty_type& diffic, uint32_t& height, const BinaryArray& ex_nonce) override; + virtual bool get_block_template(Block& b, const AccountKeys& acc, Difficulty& diffic, uint32_t& height, const BinaryArray& ex_nonce) override; virtual bool getBlockLongHash(Crypto::cn_context &context, const Block& b, Crypto::Hash& res) override; bool addObserver(ICoreObserver* observer) override; @@ -79,8 +79,8 @@ namespace CryptoNote { virtual bool getBlockReward(uint8_t blockMajorVersion, size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, uint64_t& reward, int64_t& emissionChange) override; virtual bool scanOutputkeysForIndices(const KeyInput& txInToKey, std::list>& outputReferences) override; - virtual bool getBlockDifficulty(uint32_t height, difficulty_type& difficulty) override; - virtual bool getBlockCumulativeDifficulty(uint32_t height, difficulty_type& difficulty) override; + virtual bool getBlockDifficulty(uint32_t height, uint64_t& difficulty) override; + virtual bool getBlockCumulativeDifficulty(uint32_t height, Difficulty& difficulty) override; virtual bool getBlockTimestamp(uint32_t height, uint64_t& timestamp) override; virtual bool getBlockContainingTx(const Crypto::Hash& txId, Crypto::Hash& blockId, uint32_t& blockHeight) override; virtual bool getMultisigOutputReference(const MultisignatureInput& txInMultisig, std::pair& output_reference) override; @@ -150,7 +150,7 @@ namespace CryptoNote { virtual std::vector findBlockchainSupplement(const std::vector& remoteBlockIds, size_t maxCount, uint32_t& totalBlockCount, uint32_t& startBlockIndex) override; bool get_stat_info(core_stat_info& st_inf) override; - virtual bool getblockEntry(uint32_t height, uint64_t& block_cumulative_size, difficulty_type& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) override; + virtual bool getblockEntry(uint32_t height, uint64_t& block_cumulative_size, uint64_t& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) override; virtual bool get_tx_outputs_gindexs(const Crypto::Hash& tx_id, std::vector& indexs) override; Crypto::Hash get_tail_id(); diff --git a/src/CryptoNoteCore/CryptoNoteSerialization.cpp b/src/CryptoNoteCore/CryptoNoteSerialization.cpp index 4358ad3b43..51aabfd69c 100644 --- a/src/CryptoNoteCore/CryptoNoteSerialization.cpp +++ b/src/CryptoNoteCore/CryptoNoteSerialization.cpp @@ -1,4 +1,8 @@ // Copyright (c) 2012-2016, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2014 The Boolberry +// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2016-2022, The Karbowanec developers +// // // This file is part of Karbo. // @@ -461,5 +465,29 @@ void serialize(KeyPair& keyPair, ISerializer& serializer) { serializer(keyPair.publicKey, "public_key"); } +void serialize(CryptoNote::Difficulty& difficulty, ISerializer& serializer) { + if (serializer.type() == ISerializer::OUTPUT) { + // store high part + CryptoNote::Difficulty x_ = difficulty >> 64; + uint64_t v = x_.convert_to(); + serializer(v, "hi"); + + // store low part + x_ = difficulty << 64 >> 64; + v = x_.convert_to(); + serializer(v, "lo"); + } + else { + // load high part + uint64_t v = 0; + serializer(v, "hi"); + difficulty = v; + // load low part + difficulty = difficulty << 64; + serializer(v, "lo"); + difficulty += v; + } +} + } //namespace CryptoNote diff --git a/src/CryptoNoteCore/CryptoNoteSerialization.h b/src/CryptoNoteCore/CryptoNoteSerialization.h index 0e5fad8af7..98f29ec6ff 100755 --- a/src/CryptoNoteCore/CryptoNoteSerialization.h +++ b/src/CryptoNoteCore/CryptoNoteSerialization.h @@ -1,5 +1,8 @@ // Copyright (c) 2012-2016, The CryptoNote developers, The Bytecoin developers -// +// Copyright (c) 2014 The Boolberry +// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2016-2022, The Karbowanec developers +// // This file is part of Karbo. // // Karbo is free software: you can redistribute it and/or modify @@ -20,6 +23,7 @@ #include "CryptoNoteBasic.h" #include "crypto/chacha8.h" #include "Serialization/ISerializer.h" +#include "Difficulty.h" #include "crypto/crypto.h" namespace Crypto { @@ -66,4 +70,6 @@ void serialize(AccountKeys& keys, ISerializer& s); void serialize(KeyPair& keyPair, ISerializer& serializer); +void serialize(CryptoNote::Difficulty& difficulty, ISerializer& serializer); + } diff --git a/src/CryptoNoteCore/Currency.cpp b/src/CryptoNoteCore/Currency.cpp index 7e2f740bcd..da2c02d621 100755 --- a/src/CryptoNoteCore/Currency.cpp +++ b/src/CryptoNoteCore/Currency.cpp @@ -419,8 +419,8 @@ namespace CryptoNote { return txExtraSize > 100 ? minFee / 100 * (txExtraSize - 100) : 0; } - difficulty_type Currency::nextDifficulty(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, - std::vector cumulativeDifficulties) const { + Difficulty Currency::nextDifficulty(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, + std::vector cumulativeDifficulties) const { if (blockMajorVersion >= BLOCK_MAJOR_VERSION_5) { return nextDifficultyV5(height, blockMajorVersion, timestamps, cumulativeDifficulties); } @@ -438,8 +438,8 @@ namespace CryptoNote { } } - difficulty_type Currency::nextDifficultyV1(std::vector timestamps, - std::vector cumulativeDifficulties) const { + Difficulty Currency::nextDifficultyV1(std::vector timestamps, + std::vector cumulativeDifficulties) const { assert(m_difficultyWindow >= 2); if (timestamps.size() > m_difficultyWindow) { @@ -472,11 +472,11 @@ namespace CryptoNote { timeSpan = 1; } - difficulty_type totalWork = cumulativeDifficulties[cutEnd - 1] - cumulativeDifficulties[cutBegin]; + Difficulty totalWork = cumulativeDifficulties[cutEnd - 1] - cumulativeDifficulties[cutBegin]; assert(totalWork > 0); uint64_t low, high; - low = mul128(totalWork, m_difficultyTarget, &high); + low = mul128(totalWork.convert_to(), m_difficultyTarget, &high); if (high != 0 || low + timeSpan - 1 < low) { return 0; } @@ -484,8 +484,8 @@ namespace CryptoNote { return (low + timeSpan - 1) / timeSpan; } - difficulty_type Currency::nextDifficultyV2(std::vector timestamps, - std::vector cumulativeDifficulties) const { + Difficulty Currency::nextDifficultyV2(std::vector timestamps, + std::vector cumulativeDifficulties) const { // Difficulty calculation v. 2 // based on Zawy difficulty algorithm v1.0 @@ -515,13 +515,13 @@ namespace CryptoNote { timeSpan = 1; } - difficulty_type totalWork = cumulativeDifficulties.back() - cumulativeDifficulties.front(); + Difficulty totalWork = cumulativeDifficulties.back() - cumulativeDifficulties.front(); assert(totalWork > 0); // uint64_t nextDiffZ = totalWork * m_difficultyTarget / timeSpan; uint64_t low, high; - low = mul128(totalWork, m_difficultyTarget, &high); + low = mul128(totalWork.convert_to(), m_difficultyTarget, &high); // blockchain error "Difficulty overhead" if this function returns zero if (high != 0) { return 0; @@ -537,8 +537,8 @@ namespace CryptoNote { return nextDiffZ; } - difficulty_type Currency::nextDifficultyV3(std::vector timestamps, - std::vector cumulativeDifficulties) const { + Difficulty Currency::nextDifficultyV3(std::vector timestamps, + std::vector cumulativeDifficulties) const { // LWMA difficulty algorithm // Copyright (c) 2017-2018 Zawy @@ -573,7 +573,7 @@ namespace CryptoNote { double LWMA(0), sum_inverse_D(0), harmonic_mean_D(0), nextDifficulty(0); int64_t solveTime(0); - uint64_t difficulty(0), next_difficulty(0); + CryptoNote::Difficulty difficulty(0), next_difficulty(0); // Loop through N most recent blocks. for (size_t i = 1; i <= N; i++) { @@ -606,8 +606,8 @@ namespace CryptoNote { return v < lo ? lo : v > hi ? hi : v; } - difficulty_type Currency::nextDifficultyV4(uint32_t height, uint8_t blockMajorVersion, - std::vector timestamps, std::vector cumulativeDifficulties) const { + Difficulty Currency::nextDifficultyV4(uint32_t height, uint8_t blockMajorVersion, + std::vector timestamps, std::vector cumulativeDifficulties) const { // LWMA-2 / LWMA-3 difficulty algorithm // Copyright (c) 2017-2018 Zawy, MIT License @@ -617,7 +617,7 @@ namespace CryptoNote { const int64_t T = static_cast(m_difficultyTarget); int64_t N = difficultyBlocksCount3(); int64_t L(0), ST, sum_3_ST(0); - uint64_t next_D, prev_D; + CryptoNote::Difficulty next_D, prev_D; assert(timestamps.size() == cumulativeDifficulties.size() && timestamps.size() <= static_cast(N + 1)); @@ -645,11 +645,11 @@ namespace CryptoNote { } } - next_D = uint64_t((cumulativeDifficulties[N] - cumulativeDifficulties[0]) * T * (N + 1)) / uint64_t(2 * L); + next_D = (cumulativeDifficulties[N] - cumulativeDifficulties[0]) * T * (N + 1) / uint64_t(2 * L); next_D = (next_D * 99ull) / 100ull; prev_D = cumulativeDifficulties[N] - cumulativeDifficulties[N - 1]; - next_D = clamp((uint64_t)(prev_D * 67ull / 100ull), next_D, (uint64_t)(prev_D * 150ull / 100ull)); + next_D = clamp((CryptoNote::Difficulty)(prev_D * 67ull / 100ull), next_D, (CryptoNote::Difficulty)(prev_D * 150ull / 100ull)); if (sum_3_ST < (8 * T) / 10) { next_D = (prev_D * 110ull) / 100ull; @@ -663,8 +663,8 @@ namespace CryptoNote { return next_D; } - difficulty_type Currency::nextDifficultyV5(uint32_t height, uint8_t blockMajorVersion, - std::vector timestamps, std::vector cumulativeDifficulties) const { + Difficulty Currency::nextDifficultyV5(uint32_t height, uint8_t blockMajorVersion, + std::vector timestamps, std::vector cumulativeDifficulties) const { // LWMA-1 difficulty algorithm // Copyright (c) 2017-2018 Zawy, MIT License @@ -676,7 +676,7 @@ namespace CryptoNote { height--; // there's difference between karbo1 and karbo2 here (height vs top block index) if (height == upgradeHeight(CryptoNote::BLOCK_MAJOR_VERSION_5)) { - return cumulativeDifficulties[0] / height / RESET_WORK_FACTOR_V5; + return cumulativeDifficulties[0].convert_to() / height / RESET_WORK_FACTOR_V5; } uint32_t count = (uint32_t)difficultyBlocksCountByBlockVersion(blockMajorVersion) - 1; if (height > upgradeHeight(CryptoNote::BLOCK_MAJOR_VERSION_5) && height < CryptoNote::parameters::UPGRADE_HEIGHT_V5 + count) { @@ -690,8 +690,9 @@ namespace CryptoNote { assert(timestamps.size() == cumulativeDifficulties.size()); const int64_t T = static_cast(m_difficultyTarget); - uint64_t N = std::min(difficultyBlocksCount4(), cumulativeDifficulties.size() - 1); // adjust for new epoch difficulty reset, N should be by 1 block smaller - uint64_t L(0), avg_D, next_D, i, this_timestamp(0), previous_timestamp(0); + uint64_t N = std::min(difficultyBlocksCount4(), cumulativeDifficulties.size() - 1); // adjust for new epoch difficulty reset, N should be by 1 block smaller + uint64_t i, this_timestamp(0), previous_timestamp(0); + uint64_t L(0), avg_D, next_D; previous_timestamp = timestamps[0] - T; for (i = 1; i <= N; i++) { @@ -702,7 +703,7 @@ namespace CryptoNote { previous_timestamp = this_timestamp; } if (L < N * N * T / 20) { L = N * N * T / 20; } - avg_D = (cumulativeDifficulties[N] - cumulativeDifficulties[0]) / N; + avg_D = (cumulativeDifficulties[N] - cumulativeDifficulties[0]).convert_to() / N; // Prevent round off error for small D and overflow for large D. if (avg_D > 2000000 * N * N * T) { @@ -725,7 +726,7 @@ namespace CryptoNote { return next_D; } - bool Currency::checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, + bool Currency::checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) const { if (BLOCK_MAJOR_VERSION_2 == block.majorVersion || BLOCK_MAJOR_VERSION_3 == block.majorVersion) { return false; @@ -738,7 +739,7 @@ namespace CryptoNote { return check_hash(proofOfWork, currentDiffic); } - bool Currency::checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, + bool Currency::checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) const { if (block.majorVersion < BLOCK_MAJOR_VERSION_2) { return false; @@ -779,7 +780,7 @@ namespace CryptoNote { return true; } - bool Currency::checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const { + bool Currency::checkProofOfWork(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) const { switch (block.majorVersion) { case BLOCK_MAJOR_VERSION_1: case BLOCK_MAJOR_VERSION_4: diff --git a/src/CryptoNoteCore/Currency.h b/src/CryptoNoteCore/Currency.h index 4f079f9a11..7cca2b31ff 100755 --- a/src/CryptoNoteCore/Currency.h +++ b/src/CryptoNoteCore/Currency.h @@ -164,16 +164,16 @@ class Currency { std::string formatAmount(int64_t amount) const; bool parseAmount(const std::string& str, uint64_t& amount) const; - difficulty_type nextDifficulty(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector Difficulties) const; - difficulty_type nextDifficultyV1(std::vector timestamps, std::vector Difficulties) const; - difficulty_type nextDifficultyV2(std::vector timestamps, std::vector Difficulties) const; - difficulty_type nextDifficultyV3(std::vector timestamps, std::vector Difficulties) const; - difficulty_type nextDifficultyV4(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector Difficulties) const; - difficulty_type nextDifficultyV5(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector Difficulties) const; - - bool checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const; - bool checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const; - bool checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const; + Difficulty nextDifficulty(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector Difficulties) const; + Difficulty nextDifficultyV1(std::vector timestamps, std::vector Difficulties) const; + Difficulty nextDifficultyV2(std::vector timestamps, std::vector Difficulties) const; + Difficulty nextDifficultyV3(std::vector timestamps, std::vector Difficulties) const; + Difficulty nextDifficultyV4(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector Difficulties) const; + Difficulty nextDifficultyV5(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector Difficulties) const; + + bool checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) const; + bool checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) const; + bool checkProofOfWork(Crypto::cn_context& context, const Block& block, Difficulty currentDiffic, Crypto::Hash& proofOfWork) const; size_t getApproximateMaximumInputCount(size_t transactionSize, size_t outputCount, size_t mixinCount) const; diff --git a/src/CryptoNoteCore/Difficulty.cpp b/src/CryptoNoteCore/Difficulty.cpp index 964cf8378b..9355d366e3 100644 --- a/src/CryptoNoteCore/Difficulty.cpp +++ b/src/CryptoNoteCore/Difficulty.cpp @@ -1,4 +1,7 @@ // Copyright (c) 2012-2016, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2014 The Boolberry +// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2016-2022, The Karbowanec developers // // This file is part of Karbo. // @@ -33,16 +36,16 @@ namespace CryptoNote { #if defined(__SIZEOF_INT128__) - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { + static inline void mul(uint64_t a, uint64_t b, uint64_t& low, uint64_t& high) { typedef unsigned __int128 uint128_t; - uint128_t res = (uint128_t) a * (uint128_t) b; - low = (uint64_t) res; - high = (uint64_t) (res >> 64); + uint128_t res = (uint128_t)a * (uint128_t)b; + low = (uint64_t)res; + high = (uint64_t)(res >> 64); } #else - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { + static inline void mul(uint64_t a, uint64_t b, uint64_t& low, uint64_t& high) { low = mul128(a, b, &high); } @@ -53,23 +56,62 @@ namespace CryptoNote { } static inline bool cadc(uint64_t a, uint64_t b, bool c) { - return a + b < a || (c && a + b == (uint64_t) -1); + return a + b < a || (c && a + b == (uint64_t)-1); } - bool check_hash(const Crypto::Hash &hash, difficulty_type difficulty) { + bool check_hash_64(const Crypto::Hash& hash, uint64_t difficulty) { uint64_t low, high, top, cur; // First check the highest word, this will most likely fail for a random hash. - mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high); + mul(swap64le(((const uint64_t*)&hash)[3]), difficulty, top, high); if (high != 0) { return false; } - mul(swap64le(((const uint64_t *) &hash)[0]), difficulty, low, cur); - mul(swap64le(((const uint64_t *) &hash)[1]), difficulty, low, high); + mul(swap64le(((const uint64_t*)&hash)[0]), difficulty, low, cur); + mul(swap64le(((const uint64_t*)&hash)[1]), difficulty, low, high); bool carry = cadd(cur, low); cur = high; - mul(swap64le(((const uint64_t *) &hash)[2]), difficulty, low, high); + mul(swap64le(((const uint64_t*)&hash)[2]), difficulty, low, high); carry = cadc(cur, low, carry); carry = cadc(high, top, carry); return !carry; } -} + +#if defined(_MSC_VER) +#ifdef max +#undef max +#endif +#endif + + const CryptoNote::Difficulty max64bit(std::numeric_limits::max()); + const boost::multiprecision::uint256_t max128bit(std::numeric_limits::max()); + const boost::multiprecision::uint512_t max256bit(std::numeric_limits::max()); + +#define FORCE_FULL_128_BITS + + bool check_hash_128(const Crypto::Hash& hash, CryptoNote::Difficulty difficulty) { +#ifndef FORCE_FULL_128_BITS + // fast check + if (difficulty >= max64bit && ((const uint64_t*)&hash)[3] > 0) + return false; +#endif + // usual slow check + boost::multiprecision::uint512_t hashVal = 0; +#ifdef FORCE_FULL_128_BITS + for (int i = 0; i < 4; i++) { // highest word is zero +#else + for (int i = 1; i < 4; i++) { // highest word is zero +#endif + hashVal <<= 64; + hashVal |= swap64le(((const uint64_t*)&hash)[3 - i]); + } + return hashVal * difficulty <= max256bit; + } + + bool check_hash(const Crypto::Hash & hash, CryptoNote::Difficulty difficulty) { + if (difficulty <= max64bit) // if can convert to small difficulty - do it + return check_hash_64(hash, difficulty.convert_to()); + else + return check_hash_128(hash, difficulty); + } + +} \ No newline at end of file diff --git a/src/CryptoNoteCore/Difficulty.h b/src/CryptoNoteCore/Difficulty.h index 04fbeaae19..6c754a147b 100644 --- a/src/CryptoNoteCore/Difficulty.h +++ b/src/CryptoNoteCore/Difficulty.h @@ -1,4 +1,7 @@ // Copyright (c) 2012-2016, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2014 The Boolberry +// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2016-2022, The Karbowanec developers // // This file is part of Karbo. // @@ -20,11 +23,15 @@ #include #include +#include + #include "crypto/hash.h" namespace CryptoNote { - typedef std::uint64_t difficulty_type; + typedef boost::multiprecision::uint128_t Difficulty; - bool check_hash(const Crypto::Hash &hash, difficulty_type difficulty); + bool check_hash(const Crypto::Hash &hash, Difficulty difficulty); + bool check_hash_64(const Crypto::Hash& hash, uint64_t difficulty); + bool check_hash_128(const Crypto::Hash& hash, Difficulty difficulty); } diff --git a/src/CryptoNoteCore/ICore.h b/src/CryptoNoteCore/ICore.h index 668fa963b3..851cdbd930 100755 --- a/src/CryptoNoteCore/ICore.h +++ b/src/CryptoNoteCore/ICore.h @@ -108,8 +108,8 @@ class ICore { virtual bool getBlockReward(uint8_t blockMajorVersion, size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, uint64_t& reward, int64_t& emissionChange) = 0; virtual bool scanOutputkeysForIndices(const KeyInput& txInToKey, std::list>& outputReferences) = 0; - virtual bool getBlockDifficulty(uint32_t height, difficulty_type& difficulty) = 0; - virtual bool getBlockCumulativeDifficulty(uint32_t height, difficulty_type& difficulty) = 0; + virtual bool getBlockDifficulty(uint32_t height, uint64_t& difficulty) = 0; + virtual bool getBlockCumulativeDifficulty(uint32_t height, Difficulty& difficulty) = 0; virtual bool getBlockTimestamp(uint32_t height, uint64_t& timestamp) = 0; virtual bool getBlockContainingTx(const Crypto::Hash& txId, Crypto::Hash& blockId, uint32_t& blockHeight) = 0; virtual bool getMultisigOutputReference(const MultisignatureInput& txInMultisig, std::pair& outputReference) = 0; @@ -131,7 +131,7 @@ class ICore { virtual uint8_t getBlockMajorVersionForHeight(uint32_t height) = 0; virtual uint8_t getCurrentBlockMajorVersion() = 0; virtual size_t getAlternativeBlocksCount() = 0; - virtual bool getblockEntry(uint32_t height, uint64_t& block_cumulative_size, difficulty_type& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) = 0; + virtual bool getblockEntry(uint32_t height, uint64_t& block_cumulative_size, uint64_t& difficulty, uint64_t& already_generated_coins, uint64_t& reward, uint64_t& transactions_count, uint64_t& timestamp) = 0; virtual std::unique_ptr getBlock(const Crypto::Hash& blocksId) = 0; virtual bool handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock, uint32_t height) = 0; diff --git a/src/CryptoNoteCore/IMinerHandler.h b/src/CryptoNoteCore/IMinerHandler.h index c82eefa269..6bd601f572 100644 --- a/src/CryptoNoteCore/IMinerHandler.h +++ b/src/CryptoNoteCore/IMinerHandler.h @@ -23,7 +23,7 @@ namespace CryptoNote { struct IMinerHandler { virtual bool handle_block_found(Block& b) = 0; - virtual bool get_block_template(Block& b, const AccountKeys& acc, difficulty_type& diffic, uint32_t& height, const BinaryArray& ex_nonce) = 0; + virtual bool get_block_template(Block& b, const AccountKeys& acc, Difficulty& diffic, uint32_t& height, const BinaryArray& ex_nonce) = 0; virtual bool getBlockLongHash(Crypto::cn_context &context, const Block& b, Crypto::Hash& res) = 0; protected: diff --git a/src/CryptoNoteCore/Miner.cpp b/src/CryptoNoteCore/Miner.cpp index 98c3c2ed2e..40d5612415 100644 --- a/src/CryptoNoteCore/Miner.cpp +++ b/src/CryptoNoteCore/Miner.cpp @@ -71,7 +71,7 @@ namespace CryptoNote stop(); } //----------------------------------------------------------------------------------------------------- - bool miner::set_block_template(const Block& bl, const difficulty_type& di) { + bool miner::set_block_template(const Block& bl, const Difficulty& di) { std::lock_guard lk(m_template_lock); m_template = bl; @@ -105,7 +105,7 @@ namespace CryptoNote //----------------------------------------------------------------------------------------------------- bool miner::request_block_template() { Block bl = boost::value_initialized(); - difficulty_type di = 0; + Difficulty di = 0; uint32_t height; CryptoNote::BinaryArray extra_nonce; @@ -315,7 +315,7 @@ namespace CryptoNote return true; } //----------------------------------------------------------------------------------------------------- - bool miner::find_nonce_for_given_block(Crypto::cn_context &context, Block& bl, const difficulty_type& diffic) { + bool miner::find_nonce_for_given_block(Crypto::cn_context &context, Block& bl, const Difficulty& diffic) { unsigned nthreads = std::thread::hardware_concurrency(); @@ -405,7 +405,7 @@ namespace CryptoNote { logger(INFO) << "Miner thread was started ["<< th_local_index << "]"; uint32_t nonce = m_starter_nonce + th_local_index; - difficulty_type local_diff = 0; + Difficulty local_diff = 0; uint32_t local_template_ver = 0; Crypto::cn_context context; Block b; diff --git a/src/CryptoNoteCore/Miner.h b/src/CryptoNoteCore/Miner.h index efb8b13ebe..42d9696135 100644 --- a/src/CryptoNoteCore/Miner.h +++ b/src/CryptoNoteCore/Miner.h @@ -41,7 +41,7 @@ namespace CryptoNote { ~miner(); bool init(const MinerConfig& config); - bool set_block_template(const Block& bl, const difficulty_type& diffic); + bool set_block_template(const Block& bl, const Difficulty& diffic); bool on_block_chain_update(); bool start(const AccountKeys& acc, size_t threads_count); uint64_t get_speed(); @@ -51,7 +51,7 @@ namespace CryptoNote { bool on_idle(); void on_synchronized(); //synchronous analog (for fast calls) - bool find_nonce_for_given_block(Crypto::cn_context &context, Block& bl, const difficulty_type& diffic); + bool find_nonce_for_given_block(Crypto::cn_context &context, Block& bl, const Difficulty& diffic); void pause(); void resume(); void do_print_hashrate(bool do_hr); @@ -77,7 +77,7 @@ namespace CryptoNote { Block m_template; std::atomic m_template_no; std::atomic m_starter_nonce; - difficulty_type m_diffic; + Difficulty m_diffic; std::atomic m_threads_total; std::atomic m_pausers_count; diff --git a/src/Rpc/CoreRpcServerCommandsDefinitions.h b/src/Rpc/CoreRpcServerCommandsDefinitions.h index 15e3bc9ef7..f6323af585 100755 --- a/src/Rpc/CoreRpcServerCommandsDefinitions.h +++ b/src/Rpc/CoreRpcServerCommandsDefinitions.h @@ -387,7 +387,7 @@ struct COMMAND_RPC_GET_INFO { uint32_t height; std::string top_block_hash; uint64_t difficulty; - uint64_t cumulative_difficulty; + std::string cumulative_difficulty; uint64_t max_cumulative_block_size; uint64_t next_reward; uint64_t min_fee; @@ -599,7 +599,7 @@ struct block_header_response { uint32_t height; uint32_t depth; std::string hash; - difficulty_type difficulty; + uint64_t difficulty; uint64_t reward; void serialize(ISerializer &s) { @@ -663,7 +663,7 @@ struct block_short_response { std::string hash; uint64_t transactions_count; uint64_t cumulative_size; - difficulty_type difficulty; + Difficulty difficulty; void serialize(ISerializer &s) { KV_MEMBER(timestamp) diff --git a/src/Rpc/RpcServer.cpp b/src/Rpc/RpcServer.cpp index 563db40877..f14bb8453a 100755 --- a/src/Rpc/RpcServer.cpp +++ b/src/Rpc/RpcServer.cpp @@ -1589,7 +1589,7 @@ bool RpcServer::on_get_explorer(const COMMAND_EXPLORER::request& req, COMMAND_EX struct tm* timeinfo; timeinfo = gmtime(&rawtime); - difficulty_type blockDifficulty; + uint64_t blockDifficulty; m_core.getBlockDifficulty(static_cast(i), blockDifficulty); size_t tx_cumulative_block_size; m_core.getBlockSize(blockHash, tx_cumulative_block_size); @@ -2082,10 +2082,12 @@ bool RpcServer::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RP res.block_major_version = m_core.getCurrentBlockMajorVersion(); uint64_t nextReward = m_core.currency().calculateReward(alreadyGeneratedCoins); res.next_reward = nextReward; - if (!m_core.getBlockCumulativeDifficulty(res.height - 1, res.cumulative_difficulty)) { + CryptoNote::Difficulty cumulative_difficulty; + if (!m_core.getBlockCumulativeDifficulty(res.height - 1, cumulative_difficulty)) { throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: can't get last cumulative difficulty." }; } + res.cumulative_difficulty = cumulative_difficulty.convert_to(); res.max_cumulative_block_size = (uint64_t)m_core.currency().maxBlockCumulativeSize(res.height); res.status = CORE_RPC_STATUS_OK; @@ -2425,7 +2427,7 @@ bool RpcServer::on_blocks_list_json(const COMMAND_RPC_GET_BLOCKS_LIST::request& m_core.getBlockSize(block_hash, tx_cumulative_block_size); size_t blokBlobSize = getObjectBinarySize(blk); size_t minerTxBlobSize = getObjectBinarySize(blk.baseTransaction); - difficulty_type blockDiff; + uint64_t blockDiff; m_core.getBlockDifficulty(static_cast(i), blockDiff); block_short_response block_short; @@ -2457,7 +2459,7 @@ bool RpcServer::on_alt_blocks_list_json(const COMMAND_RPC_GET_ALT_BLOCKS_LIST::r m_core.getBlockSize(block_hash, tx_cumulative_block_size); size_t blokBlobSize = getObjectBinarySize(b); size_t minerTxBlobSize = getObjectBinarySize(b.baseTransaction); - difficulty_type blockDiff; + uint64_t blockDiff; m_core.getBlockDifficulty(static_cast(block_height), blockDiff); block_short_response block_short; @@ -2626,10 +2628,13 @@ bool RpcServer::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& Block b = boost::value_initialized(); CryptoNote::BinaryArray blob_reserve; blob_reserve.resize(req.reserve_size, 0); - if (!m_core.get_block_template(b, keys, res.difficulty, res.height, blob_reserve)) { + + CryptoNote::Difficulty diff; + if (!m_core.get_block_template(b, keys, diff, res.height, blob_reserve)) { logger(Logging::ERROR) << "Failed to create block template"; throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: failed to create block template" }; } + res.difficulty = diff.convert_to(); // wide diff may be not needed, as only cumulative will ever get this high BinaryArray block_blob = toBinaryArray(b); Crypto::PublicKey tx_pub_key = CryptoNote::getTransactionPublicKeyFromExtra(b.baseTransaction.extra);