diff --git a/cryptonote/.gitattributes b/cryptonote/.gitattributes index 6afd357..a21fb22 100644 --- a/cryptonote/.gitattributes +++ b/cryptonote/.gitattributes @@ -1,2 +1,10 @@ .git* export-ignore -/CMakeLists.txt export-subst \ No newline at end of file +/CMakeLists.txt export-subst +*.sh text eol=lf +*.h text +*.c text +*.cc text +*.cpp text +*.java text +*.md text +*.rc text eol=crlf diff --git a/cryptonote/README.md b/cryptonote/README.md index 62f7084..4b5a0ac 100644 --- a/cryptonote/README.md +++ b/cryptonote/README.md @@ -59,3 +59,9 @@ Run `./src/Bittoriumd` to connect to the network and let it sync (it may take a #### Thanks Cryptonote Developers, Bytecoin Developers, Monero Developers, TurtleCoin Developers, Forknote Project, PinkstarcoinV2 Developers, Bittorium Developers. "# Bittorium" + +#### Donate +Donate to our project and help us achieve more for you! +Our BTC Address: 326LiKxxdm9tJ2KPGG353PvfgiyNpYNoQ3 + + diff --git a/cryptonote/include/INode.h b/cryptonote/include/INode.h index f63872f..5cc725c 100644 --- a/cryptonote/include/INode.h +++ b/cryptonote/include/INode.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -99,6 +100,8 @@ class INode { virtual uint32_t getLocalBlockCount() const = 0; virtual uint32_t getKnownBlockCount() const = 0; virtual uint64_t getLastLocalBlockTimestamp() const = 0; + virtual std::string getLastFeeAddress() const = 0; + virtual std::string getLastCollateralHash() const = 0; virtual void getBlockHashesByTimestamps(uint64_t timestampBegin, size_t secondsCount, std::vector& blockHashes, const Callback& callback) = 0; virtual void getTransactionHashesByPaymentId(const Crypto::Hash& paymentId, std::vector& transactionHashes, const Callback& callback) = 0; @@ -116,6 +119,8 @@ class INode { virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) = 0; virtual void getBlock(const uint32_t blockHeight, BlockDetails &block, const Callback& callback) = 0; virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) = 0; + virtual void getFeeAddress(std::string &feeAddress, const Callback& callback) = 0; + virtual void getCollateralHash(std::string &collateralHash, const Callback & callback) = 0; virtual void isSynchronized(bool& syncStatus, const Callback& callback) = 0; }; diff --git a/cryptonote/src/Common/Util.cpp b/cryptonote/src/Common/Util.cpp index f1ff324..c23082f 100644 --- a/cryptonote/src/Common/Util.cpp +++ b/cryptonote/src/Common/Util.cpp @@ -297,6 +297,25 @@ std::string get_nix_version_display_string() return ""; } + + std::wstring get_special_folder_path_w(int nfolder, bool iscreate) + { + namespace fs = boost::filesystem; + wchar_t psz_path[MAX_PATH] = L""; + + if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate)) { + return psz_path; + } + + return L""; + } + + std::wstring getDefaultDataDirectoryW() + { + std::wstring ws(strlen(CryptoNote::CRYPTONOTE_NAME), L' '); + ws.resize(std::mbstowcs(&ws[0], CryptoNote::CRYPTONOTE_NAME, strlen(CryptoNote::CRYPTONOTE_NAME))); + return get_special_folder_path_w(CSIDL_APPDATA, true) + std::wstring(L"/") + ws; + } #endif std::string getDefaultDataDirectory() diff --git a/cryptonote/src/Common/Util.h b/cryptonote/src/Common/Util.h index b33c8ee..e01a60f 100644 --- a/cryptonote/src/Common/Util.h +++ b/cryptonote/src/Common/Util.h @@ -23,6 +23,9 @@ namespace Tools { std::string getDefaultDataDirectory(); +#ifdef WIN32 + std::wstring getDefaultDataDirectoryW(); +#endif std::string getDefaultCacheFile(const std::string& dataDir); std::string get_os_version_string(); bool create_directories_if_necessary(const std::string& path); diff --git a/cryptonote/src/CryptoNoteConfig.h b/cryptonote/src/CryptoNoteConfig.h index 2da6df6..8b2cbc4 100644 --- a/cryptonote/src/CryptoNoteConfig.h +++ b/cryptonote/src/CryptoNoteConfig.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -31,15 +32,25 @@ const size_t CRYPTONOTE_MAX_TX_SIZE = 1000000000; const size_t CRYPTONOTE_MAX_SAFE_TX_SIZE = 115000; const uint64_t CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0xce; const uint32_t CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW = 10; -const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT = 60 * 60 * 2; const size_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW = 60; +const size_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V3 = 11; + +const uint64_t DIFFICULTY_TARGET = 240; // seconds +const uint64_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY = 24 * 60 * 60 / DIFFICULTY_TARGET; + +const uint32_t UPGRADE_HEIGHT_V2 = 1; +const uint32_t UPGRADE_HEIGHT_V3 = 2; +const uint32_t UPGRADE_HEIGHT_V4 = 3; // Upgrade height for CN-Lite Variant 1 switch. +const uint32_t UPGRADE_HEIGHT_V5 = 90000; // Upgrade height for LWMA-2 +const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent +const uint32_t UPGRADE_VOTING_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks +const uint32_t UPGRADE_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks +static_assert(0 < UPGRADE_VOTING_THRESHOLD && UPGRADE_VOTING_THRESHOLD <= 100, "Bad UPGRADE_VOTING_THRESHOLD"); +static_assert(UPGRADE_VOTING_WINDOW > 1, "Bad UPGRADE_VOTING_WINDOW"); // MONEY_SUPPLY - total number coins to be generated const uint64_t MONEY_SUPPLY = UINT64_C(18000000000); -const uint32_t ZAWY_DIFFICULTY_BLOCK_INDEX = 0; -const size_t ZAWY_DIFFICULTY_V2 = 0; -const uint8_t ZAWY_DIFFICULTY_DIFFICULTY_BLOCK_VERSION = 3; const unsigned EMISSION_SPEED_FACTOR = 19; const uint64_t GENESIS_BLOCK_REWARD = UINT64_C(1800000000); static_assert(EMISSION_SPEED_FACTOR <= 8 * sizeof(uint64_t), "Bad EMISSION_SPEED_FACTOR"); @@ -56,11 +67,16 @@ const uint16_t DEFAULT_MIXIN = 0; const uint16_t MINIMUM_MIXIN = 0; const uint64_t DEFAULT_DUST_THRESHOLD = UINT64_C(1); -const uint64_t DIFFICULTY_TARGET = 240; // seconds -const uint64_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY = 24 * 60 * 60 / DIFFICULTY_TARGET; +const uint32_t ZAWY_DIFFICULTY_BLOCK_INDEX = 0; +const size_t ZAWY_DIFFICULTY_V2 = 0; +const uint8_t ZAWY_DIFFICULTY_DIFFICULTY_BLOCK_VERSION = 3; +const uint64_t LWMA_2_DIFFICULTY_BLOCK_INDEX = UPGRADE_HEIGHT_V5; + const size_t DIFFICULTY_WINDOW = 17; const size_t DIFFICULTY_WINDOW_V1 = 360; const size_t DIFFICULTY_WINDOW_V2 = 360; +const size_t DIFFICULTY_WINDOW_V3 = 60; +const uint64_t DIFFICULTY_BLOCKS_COUNT_V3 = DIFFICULTY_WINDOW_V3 + 1; const size_t DIFFICULTY_CUT = 0; // timestamps to cut after sorting const size_t DIFFICULTY_CUT_V1 = 60; const size_t DIFFICULTY_CUT_V2 = 60; @@ -85,14 +101,10 @@ const size_t FUSION_TX_MIN_INPUT_COUNT = 12; const size_t FUSION_TX_MIN_IN_OUT_COUNT_RATIO = 4; const uint32_t KEY_IMAGE_CHECKING_BLOCK_INDEX = 0; -const uint32_t UPGRADE_HEIGHT_V2 = 1; -const uint32_t UPGRADE_HEIGHT_V3 = 2; -const uint32_t UPGRADE_HEIGHT_V4 = 3; // Upgrade height for CN-Lite Variant 1 switch. -const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent -const uint32_t UPGRADE_VOTING_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks -const uint32_t UPGRADE_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks -static_assert(0 < UPGRADE_VOTING_THRESHOLD && UPGRADE_VOTING_THRESHOLD <= 100, "Bad UPGRADE_VOTING_THRESHOLD"); -static_assert(UPGRADE_VOTING_WINDOW > 1, "Bad UPGRADE_VOTING_WINDOW"); + +const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V1 = 60 * 60 * 2; +const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 = 7 * DIFFICULTY_TARGET; +const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2_UPGRADE_HEIGHT = UPGRADE_HEIGHT_V5; const char CRYPTONOTE_BLOCKS_FILENAME[] = "blocks.bin"; const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexes.bin"; @@ -110,6 +122,7 @@ const uint8_t BLOCK_MAJOR_VERSION_1 = 1; const uint8_t BLOCK_MAJOR_VERSION_2 = 2; const uint8_t BLOCK_MAJOR_VERSION_3 = 3; const uint8_t BLOCK_MAJOR_VERSION_4 = 4; +const uint8_t BLOCK_MAJOR_VERSION_5 = 5; const uint8_t BLOCK_MINOR_VERSION_0 = 0; const uint8_t BLOCK_MINOR_VERSION_1 = 1; @@ -137,7 +150,9 @@ const char P2P_STAT_TRUSTED_PUB_KEY[] = ""; const char* const SEED_NODES[] = { "95.216.187.5:34902", - "95.216.187.3:34902" + "95.216.187.3:34902", + "95.216.163.155:34902", + "193.70.84.52:34902" }; } // CryptoNote diff --git a/cryptonote/src/CryptoNoteCore/BlockValidationErrors.h b/cryptonote/src/CryptoNoteCore/BlockValidationErrors.h index 5c1a0fa..ab971e9 100644 --- a/cryptonote/src/CryptoNoteCore/BlockValidationErrors.h +++ b/cryptonote/src/CryptoNoteCore/BlockValidationErrors.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -35,6 +36,7 @@ enum class BlockValidationError { BLOCK_REWARD_MISMATCH, CHECKPOINT_BLOCK_HASH_MISMATCH, PROOF_OF_WORK_TOO_WEAK, + NOT_ENOUGH_TRANSACTIONS, TRANSACTION_ABSENT_IN_POOL }; @@ -66,6 +68,7 @@ class BlockValidationErrorCategory : public std::error_category { case BlockValidationError::BLOCK_REWARD_MISMATCH: return "Block reward doesn't match expected reward"; case BlockValidationError::CHECKPOINT_BLOCK_HASH_MISMATCH: return "Checkpoint block hash mismatch"; case BlockValidationError::PROOF_OF_WORK_TOO_WEAK: return "Proof of work is too weak"; + case BlockValidationError::NOT_ENOUGH_TRANSACTIONS: return "New block must have at least one transaction"; case BlockValidationError::TRANSACTION_ABSENT_IN_POOL: return "Block's transaction is absent in transaction pool"; default: return "Unknown error"; } diff --git a/cryptonote/src/CryptoNoteCore/BlockchainCache.cpp b/cryptonote/src/CryptoNoteCore/BlockchainCache.cpp index 221283f..5c97480 100644 --- a/cryptonote/src/CryptoNoteCore/BlockchainCache.cpp +++ b/cryptonote/src/CryptoNoteCore/BlockchainCache.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -590,6 +591,16 @@ BinaryArray BlockchainCache::getRawTransaction(uint32_t index, uint32_t transact } } +BinaryArray BlockchainCache::getRawTransaction(const Crypto::Hash &transaction) const { + auto& index = transactions.get(); + auto it = index.find(transaction); + if (it == index.end()) { + return parent->getRawTransaction(transaction); + } + + return getRawTransaction(it->blockIndex, it->transactionIndex); +} + std::vector BlockchainCache::getRawTransactions(const std::vector& requestedTransactions) const { std::vector misses; @@ -957,9 +968,9 @@ Difficulty BlockchainCache::getDifficultyForNextBlock() const { Difficulty BlockchainCache::getDifficultyForNextBlock(uint32_t blockIndex) const { assert(blockIndex <= getTopBlockIndex()); uint8_t nextBlockMajorVersion = getBlockMajorVersionForHeight(blockIndex+1); - auto timestamps = getLastTimestamps(currency.difficultyBlocksCountByBlockVersion(nextBlockMajorVersion), blockIndex, skipGenesisBlock); + auto timestamps = getLastTimestamps(currency.difficultyBlocksCountByBlockVersion(nextBlockMajorVersion, blockIndex), blockIndex, skipGenesisBlock); auto commulativeDifficulties = - getLastCumulativeDifficulties(currency.difficultyBlocksCountByBlockVersion(nextBlockMajorVersion), blockIndex, skipGenesisBlock); + getLastCumulativeDifficulties(currency.difficultyBlocksCountByBlockVersion(nextBlockMajorVersion, blockIndex), blockIndex, skipGenesisBlock); return currency.nextDifficulty(nextBlockMajorVersion, blockIndex, std::move(timestamps), std::move(commulativeDifficulties)); } diff --git a/cryptonote/src/CryptoNoteCore/BlockchainCache.h b/cryptonote/src/CryptoNoteCore/BlockchainCache.h index ef48fc7..7725b6e 100644 --- a/cryptonote/src/CryptoNoteCore/BlockchainCache.h +++ b/cryptonote/src/CryptoNoteCore/BlockchainCache.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -177,6 +178,8 @@ class BlockchainCache : public IBlockchainCache { std::vector &missedTransactions) const override; virtual RawBlock getBlockByIndex(uint32_t index) const override; virtual BinaryArray getRawTransaction(uint32_t blockIndex, uint32_t transactionIndex) const override; + virtual BinaryArray getRawTransaction(const Crypto::Hash &transaction) const override; + virtual std::vector getTransactionHashes() const override; virtual std::vector getRandomOutsByAmount(uint64_t amount, size_t count, uint32_t blockIndex) const override; virtual ExtractOutputKeysResult extractKeyOutputs(uint64_t amount, uint32_t blockIndex, Common::ArrayView globalIndexes, diff --git a/cryptonote/src/CryptoNoteCore/Core.cpp b/cryptonote/src/CryptoNoteCore/Core.cpp index 675d112..fb29483 100644 --- a/cryptonote/src/CryptoNoteCore/Core.cpp +++ b/cryptonote/src/CryptoNoteCore/Core.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -200,6 +201,7 @@ Core::Core(const Currency& currency, Logging::ILogger& logger, Checkpoints&& che upgradeManager->addMajorBlockVersion(BLOCK_MAJOR_VERSION_2, currency.upgradeHeight(BLOCK_MAJOR_VERSION_2)); upgradeManager->addMajorBlockVersion(BLOCK_MAJOR_VERSION_3, currency.upgradeHeight(BLOCK_MAJOR_VERSION_3)); upgradeManager->addMajorBlockVersion(BLOCK_MAJOR_VERSION_4, currency.upgradeHeight(BLOCK_MAJOR_VERSION_4)); + upgradeManager->addMajorBlockVersion(BLOCK_MAJOR_VERSION_5, currency.upgradeHeight(BLOCK_MAJOR_VERSION_5)); transactionPool = std::unique_ptr(new TransactionPoolCleanWrapper( std::unique_ptr(new TransactionPool(logger)), @@ -458,6 +460,39 @@ bool Core::queryBlocksLite(const std::vector& knownBlockHashes, ui } } +bool Core::getTransaction(const Crypto::Hash& transactionHash, BinaryArray& transaction) const { + assert(!chainsLeaves.empty()); + assert(!chainsStorage.empty()); + throwIfNotInitialized(); + + IBlockchainCache* segment = chainsLeaves[0]; + assert(segment != nullptr); + + // find in main chain + do { + if (segment->hasTransaction(transactionHash)) { + transaction = segment->getRawTransaction(transactionHash); + return true; + } + segment = segment->getParent(); + } while (segment != nullptr); + + // find in alternative chains + for (size_t chain = 1; chain < chainsLeaves.size(); ++chain) { + segment = chainsLeaves[chain]; + + while (mainChainSet.count(segment) == 0) { + if (segment->hasTransaction(transactionHash)) { + transaction = segment->getRawTransaction(transactionHash); + return true; + } + segment = segment->getParent(); + } + } + + return false; +} + void Core::getTransactions(const std::vector& transactionHashes, std::vector& transactions, std::vector& missedHashes) const { assert(!chainsLeaves.empty()); @@ -519,7 +554,7 @@ Difficulty Core::getDifficultyForNextBlock() const { uint8_t nextBlockMajorVersion = getBlockMajorVersionForHeight(topBlockIndex); - size_t blocksCount = std::min(static_cast(topBlockIndex), currency.difficultyBlocksCountByBlockVersion(nextBlockMajorVersion)); + size_t blocksCount = std::min(static_cast(topBlockIndex), currency.difficultyBlocksCountByBlockVersion(nextBlockMajorVersion, topBlockIndex)); auto timestamps = mainChain->getLastTimestamps(blocksCount); auto difficulties = mainChain->getLastCumulativeDifficulties(blocksCount); @@ -593,6 +628,11 @@ std::error_code Core::addBlock(const CachedBlock& cachedBlock, RawBlock&& rawBlo return blockValidationResult; } + if (blockTemplate.majorVersion >= BLOCK_MAJOR_VERSION_5 && blockTemplate.transactionHashes.size() < 1) { + logger(Logging::WARNING) << "New block must have at least one transaction"; + return error::BlockValidationError::NOT_ENOUGH_TRANSACTIONS; + } + auto currentDifficulty = cache->getDifficultyForNextBlock(previousBlockIndex); if (currentDifficulty == 0) { logger(Logging::DEBUGGING) << "Block " << blockStr << " has difficulty overhead"; @@ -1056,7 +1096,15 @@ bool Core::getBlockTemplate(BlockTemplate& b, const AccountPublicAddress& adr, c b.previousBlockHash = getTopBlockHash(); b.timestamp = time(nullptr); - uint64_t blockchain_timestamp_check_window = parameters::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW; + uint64_t blockchain_timestamp_check_window; + if (height >= parameters::LWMA_2_DIFFICULTY_BLOCK_INDEX) + { + blockchain_timestamp_check_window = parameters::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V3; + } + else + { + blockchain_timestamp_check_window = parameters::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW; + } /* Skip the first N blocks, we don't have enough blocks to calculate a proper median yet */ if (height >= blockchain_timestamp_check_window) { @@ -1149,6 +1197,11 @@ bool Core::getBlockTemplate(BlockTemplate& b, const AccountPublicAddress& adr, c return false; } + if (b.majorVersion >= BLOCK_MAJOR_VERSION_5 && b.transactionHashes.size() < 1) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "New block must have at least one transaction"; + return false; + } + return true; } @@ -1408,6 +1461,7 @@ std::error_code Core::validateBlock(const CachedBlock& cachedBlock, IBlockchainC minerReward = 0; if (upgradeManager->getBlockMajorVersion(cachedBlock.getBlockIndex()) != block.majorVersion) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "Expected block major version " << static_cast(upgradeManager->getBlockMajorVersion(cachedBlock.getBlockIndex())) << ", got " << static_cast(block.majorVersion); return error::BlockValidationError::WRONG_VERSION; } @@ -1424,7 +1478,7 @@ std::error_code Core::validateBlock(const CachedBlock& cachedBlock, IBlockchainC } } - if (block.timestamp > getAdjustedTime() + currency.blockFutureTimeLimit()) { + if (block.timestamp > getAdjustedTime() + currency.blockFutureTimeLimit(previousBlockIndex+1)) { return error::BlockValidationError::TIMESTAMP_TOO_FAR_IN_FUTURE; } @@ -1870,7 +1924,7 @@ void Core::fillBlockTemplate(BlockTemplate& block, size_t medianSize, size_t max block.transactionHashes.emplace_back(cachedTransaction.getTransactionHash()); logger(Logging::TRACE) << "Transaction " << cachedTransaction.getTransactionHash() << " included to block template"; } else { - logger(Logging::TRACE) << "Transaction " << cachedTransaction.getTransactionHash() << " is failed to include to block template"; + logger(Logging::TRACE) << "Failed to include transaction " << cachedTransaction.getTransactionHash() << " to block template"; } } } diff --git a/cryptonote/src/CryptoNoteCore/Core.h b/cryptonote/src/CryptoNoteCore/Core.h index 9ccfa94..5a4bbb0 100644 --- a/cryptonote/src/CryptoNoteCore/Core.h +++ b/cryptonote/src/CryptoNoteCore/Core.h @@ -73,6 +73,7 @@ class Core : public ICore, public ICoreInformation { uint32_t& startIndex, uint32_t& currentIndex, uint32_t& fullOffset, std::vector& entries) const override; virtual bool hasTransaction(const Crypto::Hash& transactionHash) const override; + virtual bool getTransaction(const Crypto::Hash& transactionHash, BinaryArray& transaction) const; virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, std::vector& missedHashes) const override; virtual Difficulty getBlockDifficulty(uint32_t blockIndex) const override; diff --git a/cryptonote/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp b/cryptonote/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp index 3e772ae..de81ad3 100644 --- a/cryptonote/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp +++ b/cryptonote/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp @@ -171,7 +171,7 @@ bool constructTransaction( //fill inputs for (const TransactionSourceEntry& src_entr : sources) { if (src_entr.realOutput >= src_entr.outputs.size()) { - logger(ERROR) << "real_output index (" << src_entr.realOutput << ")bigger than output_keys.size()=" << src_entr.outputs.size(); + logger(ERROR) << "real_output index (" << src_entr.realOutput << ") bigger than output_keys.size()=" << src_entr.outputs.size(); return false; } summary_inputs_money += src_entr.amount; @@ -307,7 +307,7 @@ bool checkOutsValid(const TransactionPrefix& tx, std::string* error) { if (out.target.type() == typeid(KeyOutput)) { if (out.amount == 0) { if (error) { - *error = "Zero amount ouput"; + *error = "Zero amount output"; } return false; } diff --git a/cryptonote/src/CryptoNoteCore/CryptoNoteSerialization.cpp b/cryptonote/src/CryptoNoteCore/CryptoNoteSerialization.cpp index b85a8ec..f435688 100644 --- a/cryptonote/src/CryptoNoteCore/CryptoNoteSerialization.cpp +++ b/cryptonote/src/CryptoNoteCore/CryptoNoteSerialization.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -366,7 +367,7 @@ void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) { void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) { serializer(header.majorVersion, "major_version"); - if (header.majorVersion > BLOCK_MAJOR_VERSION_4) { + if (header.majorVersion > BLOCK_MAJOR_VERSION_5) { throw std::runtime_error("Wrong major version"); } diff --git a/cryptonote/src/CryptoNoteCore/Currency.cpp b/cryptonote/src/CryptoNoteCore/Currency.cpp index 887fb48..962e924 100644 --- a/cryptonote/src/CryptoNoteCore/Currency.cpp +++ b/cryptonote/src/CryptoNoteCore/Currency.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers -// Copyright (c) 2018, The Bittorium developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -120,7 +120,9 @@ bool Currency::generateGenesisBlock() { } size_t Currency::difficultyWindowByBlockVersion(uint8_t blockMajorVersion) const { - if (blockMajorVersion >= BLOCK_MAJOR_VERSION_3) { + if (blockMajorVersion >= BLOCK_MAJOR_VERSION_5) { + return 60; + } else if (blockMajorVersion >= BLOCK_MAJOR_VERSION_3 && blockMajorVersion < BLOCK_MAJOR_VERSION_5) { return m_difficultyWindow; } else if (blockMajorVersion == BLOCK_MAJOR_VERSION_2) { return CryptoNote::parameters::DIFFICULTY_WINDOW_V2; @@ -149,7 +151,12 @@ size_t Currency::difficultyCutByBlockVersion(uint8_t blockMajorVersion) const { } } -size_t Currency::difficultyBlocksCountByBlockVersion(uint8_t blockMajorVersion) const { +size_t Currency::difficultyBlocksCountByBlockVersion(uint8_t blockMajorVersion, uint32_t height) const { + if (height >= parameters::LWMA_2_DIFFICULTY_BLOCK_INDEX) + { + return CryptoNote::parameters::DIFFICULTY_BLOCKS_COUNT_V3; + } + return difficultyWindowByBlockVersion(blockMajorVersion) + difficultyLagByBlockVersion(blockMajorVersion); } @@ -170,6 +177,8 @@ uint32_t Currency::upgradeHeight(uint8_t majorVersion) const { return m_upgradeHeightV3; } else if (majorVersion == BLOCK_MAJOR_VERSION_4) { return m_upgradeHeightV4; + } else if (majorVersion == BLOCK_MAJOR_VERSION_5) { + return m_upgradeHeightV5; } else { return static_cast(-1); } @@ -436,18 +445,21 @@ bool Currency::parseAmount(const std::string& str, uint64_t& amount) const { return Common::fromString(strAmount, amount); } -Difficulty Currency::nextDifficulty(std::vector timestamps, +Difficulty Currency::nextDifficultyDefault(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const { - assert(m_difficultyWindow >= 2); + size_t c_difficultyWindow = difficultyWindowByBlockVersion(version); + size_t c_difficultyCut = difficultyCutByBlockVersion(version); - if (timestamps.size() > m_difficultyWindow) { - timestamps.resize(m_difficultyWindow); - cumulativeDifficulties.resize(m_difficultyWindow); + assert(c_difficultyWindow >= 2); + + if (timestamps.size() > c_difficultyWindow) { + timestamps.resize(c_difficultyWindow); + cumulativeDifficulties.resize(c_difficultyWindow); } size_t length = timestamps.size(); assert(length == cumulativeDifficulties.size()); - assert(length <= m_difficultyWindow); + assert(length <= c_difficultyWindow); if (length <= 1) { return 1; } @@ -455,15 +467,15 @@ Difficulty Currency::nextDifficulty(std::vector timestamps, sort(timestamps.begin(), timestamps.end()); size_t cutBegin, cutEnd; - assert(2 * m_difficultyCut <= m_difficultyWindow - 2); - if (length <= m_difficultyWindow - 2 * m_difficultyCut) { + assert(2 * c_difficultyCut <= c_difficultyWindow - 2); + if (length <= c_difficultyWindow - 2 * c_difficultyCut) { cutBegin = 0; cutEnd = length; } else { - cutBegin = (length - (m_difficultyWindow - 2 * m_difficultyCut) + 1) / 2; - cutEnd = cutBegin + (m_difficultyWindow - 2 * m_difficultyCut); + cutBegin = (length - (c_difficultyWindow - 2 * c_difficultyCut) + 1) / 2; + cutEnd = cutBegin + (c_difficultyWindow - 2 * c_difficultyCut); } - assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length); + assert(cutBegin + 2 <= cutEnd && cutEnd <= length); uint64_t timeSpan = timestamps[cutEnd - 1] - timestamps[cutBegin]; if (timeSpan == 0) { timeSpan = 1; @@ -478,14 +490,64 @@ Difficulty Currency::nextDifficulty(std::vector timestamps, return 0; } - return (low + timeSpan - 1) / timeSpan; + return (low + timeSpan - 1) / timeSpan; // with version } -Difficulty Currency::nextDifficulty(uint8_t version, uint32_t blockIndex, std::vector timestamps, +Difficulty Currency::nextDifficultyBuggedZawy(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const { +/* + Calculating 'low' and 'timespan' with hardcoded values: + DIFFICULTY_CUT=0 + DIFFICULTY_LAG=0 + DIFFICULTY_WINDOW=17 +*/ + size_t c_difficultyWindow = 17; + size_t c_difficultyCut = 0; + + assert(c_difficultyWindow >= 2); + + size_t t_difficultyWindow = std::min(c_difficultyWindow, timestamps.size()); + std::vector timestamps_tmp(timestamps.end() - t_difficultyWindow, timestamps.end()); + std::vector cumulativeDifficulties_tmp(cumulativeDifficulties.end() - t_difficultyWindow, cumulativeDifficulties.end()); + + size_t length = timestamps_tmp.size(); + assert(length == cumulativeDifficulties_tmp.size()); + assert(length <= c_difficultyWindow); + if (length <= 1) { + return 1; + } + + sort(timestamps_tmp.begin(), timestamps_tmp.end()); + + assert(2 * c_difficultyCut <= c_difficultyWindow - 2); + size_t cutBegin, cutEnd; + if (length <= c_difficultyWindow - 2 * c_difficultyCut) { + cutBegin = 0; + cutEnd = length; + } else { + cutBegin = (length - (c_difficultyWindow - 2 * c_difficultyCut) + 1) / 2; + cutEnd = cutBegin + (c_difficultyWindow - 2 * c_difficultyCut); + } + assert(cutBegin + 2 <= cutEnd && cutEnd <= length); + uint64_t timeSpan = timestamps_tmp[cutEnd - 1] - timestamps_tmp[cutBegin]; + if (timeSpan == 0) { + timeSpan = 1; + } + + Difficulty totalWork = cumulativeDifficulties_tmp[cutEnd - 1] - cumulativeDifficulties_tmp[cutBegin]; + assert(totalWork > 0); -std::vector timestamps_o(timestamps); -std::vector cumulativeDifficulties_o(cumulativeDifficulties); + uint64_t low, high; + low = mul128(totalWork, m_difficultyTarget, &high); + if (high != 0 || std::numeric_limits::max() - low < (timeSpan - 1)) { + return 0; + } + + return std::max(UINT64_C(100), low / timeSpan); +} + +Difficulty Currency::nextDifficultyZawyV1(uint8_t version, uint32_t blockIndex, std::vector timestamps, + std::vector cumulativeDifficulties) const { size_t c_difficultyWindow = difficultyWindowByBlockVersion(version); size_t c_difficultyCut = difficultyCutByBlockVersion(version); @@ -514,7 +576,7 @@ std::vector cumulativeDifficulties_o(cumulativeDifficulties); cutBegin = (length - (c_difficultyWindow - 2 * c_difficultyCut) + 1) / 2; cutEnd = cutBegin + (c_difficultyWindow - 2 * c_difficultyCut); } - assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length); + assert(cutBegin + 2 <= cutEnd && cutEnd <= length); uint64_t timeSpan = timestamps[cutEnd - 1] - timestamps[cutBegin]; if (timeSpan == 0) { timeSpan = 1; @@ -529,80 +591,58 @@ std::vector cumulativeDifficulties_o(cumulativeDifficulties); return 0; } - uint8_t c_zawyDifficultyBlockVersion = m_zawyDifficultyBlockVersion; - if (m_zawyDifficultyV2) { - c_zawyDifficultyBlockVersion = 2; - } - if (version >= c_zawyDifficultyBlockVersion && c_zawyDifficultyBlockVersion) { - if (high != 0) { - return 0; - } - uint64_t nextDiffZ = low / timeSpan; + return std::max(UINT64_C(1), low / timeSpan); +} - return nextDiffZ; +Difficulty Currency::nextDifficultyZawyLWMA2(uint8_t version, uint32_t blockIndex, std::vector timestamps, + std::vector cumulativeDifficulties) const { + int64_t T = parameters::DIFFICULTY_TARGET; + int64_t N = parameters::DIFFICULTY_WINDOW_V3; + int64_t FTL = 3 * T; + int64_t L(0), ST, sum_3_ST(0), next_D, prev_D; + + if (timestamps.size() <= 10) { + return 100; } + if (timestamps.size() < static_cast(parameters::DIFFICULTY_BLOCKS_COUNT_V3)) { + N = timestamps.size()-1; + } + + assert(timestamps.size() == cumulativeDifficulties.size() && timestamps.size() <= static_cast(N + 1)); - if (m_zawyDifficultyBlockIndex && m_zawyDifficultyBlockIndex <= blockIndex) { - if (high != 0) { - return 0; - } - -/* - Recalculating 'low' and 'timespan' with hardcoded values: - DIFFICULTY_CUT=0 - DIFFICULTY_LAG=0 - DIFFICULTY_WINDOW=17 -*/ - c_difficultyWindow = 17; - c_difficultyCut = 0; - - assert(c_difficultyWindow >= 2); + for (int64_t i = 1; i <= N; i++) { + ST = std::max(-FTL, std::min( static_cast(timestamps[i]) - static_cast(timestamps[i-1]), 6*T)); + L += ST * i; + if (i > N-3) { + sum_3_ST += ST; + } + } + next_D = (static_cast(cumulativeDifficulties[N] - cumulativeDifficulties[0])*T*(N+1)*99)/(100*2*L); - size_t t_difficultyWindow = c_difficultyWindow; - if (c_difficultyWindow > timestamps.size()) { - t_difficultyWindow = timestamps.size(); - } - std::vector timestamps_tmp(timestamps_o.end() - t_difficultyWindow, timestamps_o.end()); - std::vector cumulativeDifficulties_tmp(cumulativeDifficulties_o.end() - t_difficultyWindow, cumulativeDifficulties_o.end()); - - length = timestamps_tmp.size(); - assert(length == cumulativeDifficulties_tmp.size()); - assert(length <= c_difficultyWindow); - if (length <= 1) { - return 1; - } + prev_D = cumulativeDifficulties[N] - cumulativeDifficulties[N-1]; + next_D = std::max((prev_D*67)/100, std::min(next_D, (prev_D*150)/100)); + if (sum_3_ST < (8*T)/10) { + next_D = std::max(next_D, (prev_D*110)/100); + } - sort(timestamps_tmp.begin(), timestamps_tmp.end()); + return static_cast(next_D); +} - assert(2 * c_difficultyCut <= c_difficultyWindow - 2); - if (length <= c_difficultyWindow - 2 * c_difficultyCut) { - cutBegin = 0; - cutEnd = length; - } else { - cutBegin = (length - (c_difficultyWindow - 2 * c_difficultyCut) + 1) / 2; - cutEnd = cutBegin + (c_difficultyWindow - 2 * c_difficultyCut); - } - assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length); - timeSpan = timestamps_tmp[cutEnd - 1] - timestamps_tmp[cutBegin]; - if (timeSpan == 0) { - timeSpan = 1; - } +Difficulty Currency::nextDifficulty(uint8_t version, uint32_t blockIndex, std::vector timestamps, + std::vector cumulativeDifficulties) const { + if (blockIndex >= parameters::LWMA_2_DIFFICULTY_BLOCK_INDEX) { // LWMA-2 + return nextDifficultyZawyLWMA2(version, blockIndex, timestamps, cumulativeDifficulties); + } - totalWork = cumulativeDifficulties_tmp[cutEnd - 1] - cumulativeDifficulties_tmp[cutBegin]; - assert(totalWork > 0); + if (version >= m_zawyDifficultyBlockVersion) { // Zawy v1 + return nextDifficultyZawyV1(version, blockIndex, timestamps, cumulativeDifficulties); + } - low = mul128(totalWork, m_difficultyTarget, &high); - if (high != 0 || std::numeric_limits::max() - low < (timeSpan - 1)) { - return 0; - } - uint64_t nextDiffZ = low / timeSpan; - if (nextDiffZ <= 100) { - nextDiffZ = 100; - } - return nextDiffZ; + if (m_zawyDifficultyBlockIndex && m_zawyDifficultyBlockIndex <= blockIndex) { + return nextDifficultyBuggedZawy(version, blockIndex, timestamps, cumulativeDifficulties); } - return (low + timeSpan - 1) / timeSpan; // with version + return nextDifficultyDefault(version, blockIndex, timestamps, cumulativeDifficulties); } bool Currency::checkProofOfWorkV1(Crypto::cn_context& context, const CachedBlock& block, Difficulty currentDifficulty) const { @@ -690,7 +730,8 @@ m_maxTxSize(currency.m_maxTxSize), m_publicAddressBase58Prefix(currency.m_publicAddressBase58Prefix), m_minedMoneyUnlockWindow(currency.m_minedMoneyUnlockWindow), m_timestampCheckWindow(currency.m_timestampCheckWindow), -m_blockFutureTimeLimit(currency.m_blockFutureTimeLimit), +m_blockFutureTimeLimitV1(currency.m_blockFutureTimeLimitV1), +m_blockFutureTimeLimitV2(currency.m_blockFutureTimeLimitV2), m_moneySupply(currency.m_moneySupply), m_emissionSpeedFactor(currency.m_emissionSpeedFactor), m_rewardBlocksWindow(currency.m_rewardBlocksWindow), @@ -718,6 +759,7 @@ m_fusionTxMinInOutCountRatio(currency.m_fusionTxMinInOutCountRatio), m_upgradeHeightV2(currency.m_upgradeHeightV2), m_upgradeHeightV3(currency.m_upgradeHeightV3), m_upgradeHeightV4(currency.m_upgradeHeightV4), +m_upgradeHeightV5(currency.m_upgradeHeightV5), m_upgradeVotingThreshold(currency.m_upgradeVotingThreshold), m_upgradeVotingWindow(currency.m_upgradeVotingWindow), m_upgradeWindow(currency.m_upgradeWindow), @@ -742,16 +784,17 @@ CurrencyBuilder::CurrencyBuilder(Logging::ILogger& log) : m_currency(log) { minedMoneyUnlockWindow(parameters::CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW); timestampCheckWindow(parameters::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW); - blockFutureTimeLimit(parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT); + blockFutureTimeLimitV1(parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V1); + blockFutureTimeLimitV2(parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2); moneySupply(parameters::MONEY_SUPPLY); emissionSpeedFactor(parameters::EMISSION_SPEED_FACTOR); -genesisBlockReward(parameters::GENESIS_BLOCK_REWARD); + genesisBlockReward(parameters::GENESIS_BLOCK_REWARD); rewardBlocksWindow(parameters::CRYPTONOTE_REWARD_BLOCKS_WINDOW); -zawyDifficultyBlockIndex(parameters::ZAWY_DIFFICULTY_BLOCK_INDEX); -zawyDifficultyV2(parameters::ZAWY_DIFFICULTY_V2); -zawyDifficultyBlockVersion(parameters::ZAWY_DIFFICULTY_DIFFICULTY_BLOCK_VERSION); + zawyDifficultyBlockIndex(parameters::ZAWY_DIFFICULTY_BLOCK_INDEX); + zawyDifficultyV2(parameters::ZAWY_DIFFICULTY_V2); + zawyDifficultyBlockVersion(parameters::ZAWY_DIFFICULTY_DIFFICULTY_BLOCK_VERSION); blockGrantedFullRewardZone(parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE); minerTxBlobReservedSize(parameters::CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); @@ -783,6 +826,7 @@ zawyDifficultyBlockVersion(parameters::ZAWY_DIFFICULTY_DIFFICULTY_BLOCK_VERSION) upgradeHeightV2(parameters::UPGRADE_HEIGHT_V2); upgradeHeightV3(parameters::UPGRADE_HEIGHT_V3); upgradeHeightV4(parameters::UPGRADE_HEIGHT_V4); + upgradeHeightV5(parameters::UPGRADE_HEIGHT_V5); upgradeVotingThreshold(parameters::UPGRADE_VOTING_THRESHOLD); upgradeVotingWindow(parameters::UPGRADE_VOTING_WINDOW); upgradeWindow(parameters::UPGRADE_WINDOW); diff --git a/cryptonote/src/CryptoNoteCore/Currency.h b/cryptonote/src/CryptoNoteCore/Currency.h index ac706b3..048576c 100644 --- a/cryptonote/src/CryptoNoteCore/Currency.h +++ b/cryptonote/src/CryptoNoteCore/Currency.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -41,7 +42,13 @@ class Currency { uint32_t minedMoneyUnlockWindow() const { return m_minedMoneyUnlockWindow; } size_t timestampCheckWindow() const { return m_timestampCheckWindow; } - uint64_t blockFutureTimeLimit() const { return m_blockFutureTimeLimit; } + uint64_t blockFutureTimeLimit(uint32_t height) const { + if (height < parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2_UPGRADE_HEIGHT) { + return m_blockFutureTimeLimitV1; + } else { + return m_blockFutureTimeLimitV2; + } + } uint64_t moneySupply() const { return m_moneySupply; } unsigned int emissionSpeedFactor() const { return m_emissionSpeedFactor; } @@ -63,13 +70,13 @@ class Currency { uint64_t difficultyTarget() const { return m_difficultyTarget; } size_t difficultyWindow() const { return m_difficultyWindow; } -size_t difficultyWindowByBlockVersion(uint8_t blockMajorVersion) const; + size_t difficultyWindowByBlockVersion(uint8_t blockMajorVersion) const; size_t difficultyLag() const { return m_difficultyLag; } -size_t difficultyLagByBlockVersion(uint8_t blockMajorVersion) const; + size_t difficultyLagByBlockVersion(uint8_t blockMajorVersion) const; size_t difficultyCut() const { return m_difficultyCut; } -size_t difficultyCutByBlockVersion(uint8_t blockMajorVersion) const; + size_t difficultyCutByBlockVersion(uint8_t blockMajorVersion) const; size_t difficultyBlocksCount() const { return m_difficultyWindow + m_difficultyLag; } -size_t difficultyBlocksCountByBlockVersion(uint8_t blockMajorVersion) const; + size_t difficultyBlocksCountByBlockVersion(uint8_t blockMajorVersion, uint32_t height) const; size_t maxBlockSizeInitial() const { return m_maxBlockSizeInitial; } uint64_t maxBlockSizeGrowthSpeedNumerator() const { return m_maxBlockSizeGrowthSpeedNumerator; } @@ -125,8 +132,7 @@ size_t difficultyBlocksCountByBlockVersion(uint8_t blockMajorVersion) const; std::string formatAmount(int64_t amount) const; bool parseAmount(const std::string& str, uint64_t& amount) const; - Difficulty nextDifficulty(std::vector timestamps, std::vector cumulativeDifficulties) const; -Difficulty nextDifficulty(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const; + Difficulty nextDifficulty(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const; bool checkProofOfWorkV1(Crypto::cn_context& context, const CachedBlock& block, Difficulty currentDifficulty) const; bool checkProofOfWorkV2(Crypto::cn_context& context, const CachedBlock& block, Difficulty currentDifficulty) const; @@ -144,6 +150,11 @@ Difficulty nextDifficulty(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const; + Difficulty nextDifficultyBuggedZawy(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const; + Difficulty nextDifficultyZawyV1(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const; + Difficulty nextDifficultyZawyLWMA2(uint8_t version, uint32_t blockIndex, std::vector timestamps, std::vector cumulativeDifficulties) const; + private: uint32_t m_maxBlockHeight; size_t m_maxBlockBlobSize; @@ -152,7 +163,8 @@ Difficulty nextDifficulty(uint8_t version, uint32_t blockIndex, std::vectorsecond.blockIndex); + if (blockIt == blocksMap.end()) { + logger(Logging::ERROR) << "detected missing transaction for hash " << transaction << " in getRawTransaction"; + return BinaryArray(); + } + + if (transactionIt->second.transactionIndex == 0) { + auto block = fromBinaryArray(blockIt->second.block); + return toBinaryArray(block.baseTransaction); + } else { + assert(blockIt->second.transactions.size() >= transactionIt->second.transactionIndex - 1); + return blockIt->second.transactions[transactionIt->second.transactionIndex - 1]; + } +} + std::vector DatabaseBlockchainCache::getTransactionHashes() const { assert(false); return {}; diff --git a/cryptonote/src/CryptoNoteCore/DatabaseBlockchainCache.h b/cryptonote/src/CryptoNoteCore/DatabaseBlockchainCache.h index 96a8cfc..8b25423 100644 --- a/cryptonote/src/CryptoNoteCore/DatabaseBlockchainCache.h +++ b/cryptonote/src/CryptoNoteCore/DatabaseBlockchainCache.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -148,6 +149,7 @@ class DatabaseBlockchainCache : public IBlockchainCache { std::vector& missedTransactions) const override; virtual RawBlock getBlockByIndex(uint32_t index) const override; virtual BinaryArray getRawTransaction(uint32_t blockIndex, uint32_t transactionIndex) const override; + virtual BinaryArray getRawTransaction(const Crypto::Hash &transaction) const override; virtual std::vector getTransactionHashes() const override; virtual std::vector getRandomOutsByAmount(uint64_t amount, size_t count, uint32_t blockIndex) const override; diff --git a/cryptonote/src/CryptoNoteCore/IBlockchainCache.h b/cryptonote/src/CryptoNoteCore/IBlockchainCache.h index b8f4640..b665dca 100644 --- a/cryptonote/src/CryptoNoteCore/IBlockchainCache.h +++ b/cryptonote/src/CryptoNoteCore/IBlockchainCache.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium Project // // This file is part of Bytecoin. // @@ -85,6 +86,7 @@ class IBlockchainCache { virtual RawBlock getBlockByIndex(uint32_t index) const = 0; virtual BinaryArray getRawTransaction(uint32_t blockIndex, uint32_t transactionIndex) const = 0; + virtual BinaryArray getRawTransaction(const Crypto::Hash &transaction) const = 0; virtual std::unique_ptr split(uint32_t splitBlockIndex) = 0; virtual void pushBlock( const CachedBlock& cachedBlock, diff --git a/cryptonote/src/CryptoNoteCore/RocksDBWrapper.cpp b/cryptonote/src/CryptoNoteCore/RocksDBWrapper.cpp index 8f8dbe6..9a83d07 100644 --- a/cryptonote/src/CryptoNoteCore/RocksDBWrapper.cpp +++ b/cryptonote/src/CryptoNoteCore/RocksDBWrapper.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -87,7 +88,7 @@ void RocksDBWrapper::shutdown() { state.store(NOT_INITIALIZED); } -void RocksDBWrapper::destoy(const DataBaseConfig& config) { +void RocksDBWrapper::destroy(const DataBaseConfig& config) { if (state.load() != NOT_INITIALIZED) { throw std::system_error(make_error_code(CryptoNote::error::DataBaseErrorCodes::ALREADY_INITIALIZED)); } diff --git a/cryptonote/src/CryptoNoteCore/RocksDBWrapper.h b/cryptonote/src/CryptoNoteCore/RocksDBWrapper.h index abf1308..bb7e62a 100644 --- a/cryptonote/src/CryptoNoteCore/RocksDBWrapper.h +++ b/cryptonote/src/CryptoNoteCore/RocksDBWrapper.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -43,7 +44,7 @@ class RocksDBWrapper : public IDataBase { void init(const DataBaseConfig& config); void shutdown(); - void destoy(const DataBaseConfig& config); //Be careful with this method! + void destroy(const DataBaseConfig& config); //Be careful with this method! std::error_code write(IWriteBatch& batch) override; std::error_code writeSync(IWriteBatch& batch) override; diff --git a/cryptonote/src/CryptoNoteCore/TransactionUtils.cpp b/cryptonote/src/CryptoNoteCore/TransactionUtils.cpp index 0d2db63..877d10a 100644 --- a/cryptonote/src/CryptoNoteCore/TransactionUtils.cpp +++ b/cryptonote/src/CryptoNoteCore/TransactionUtils.cpp @@ -89,6 +89,14 @@ const TransactionInput& getInputChecked(const CryptoNote::TransactionPrefix& tra // TransactionOutput helper functions +uint64_t getTransactionOutputAmount(const TransactionOutput& out) { + if (out.target.type() == typeid(KeyOutput)) { + return out.amount; + } + + return 0; +} + TransactionTypes::OutputType getTransactionOutputType(const TransactionOutputTarget& out) { if (out.type() == typeid(KeyOutput)) { return TransactionTypes::OutputType::Key; diff --git a/cryptonote/src/CryptoNoteCore/TransactionUtils.h b/cryptonote/src/CryptoNoteCore/TransactionUtils.h index 7e64e2a..bc8e831 100644 --- a/cryptonote/src/CryptoNoteCore/TransactionUtils.h +++ b/cryptonote/src/CryptoNoteCore/TransactionUtils.h @@ -32,6 +32,7 @@ const TransactionInput& getInputChecked(const CryptoNote::TransactionPrefix& tra bool isOutToKey(const Crypto::PublicKey& spendPublicKey, const Crypto::PublicKey& outKey, const Crypto::KeyDerivation& derivation, size_t keyIndex); // TransactionOutput helper functions +uint64_t getTransactionOutputAmount(const TransactionOutput& out); TransactionTypes::OutputType getTransactionOutputType(const TransactionOutputTarget& out); const TransactionOutput& getOutputChecked(const CryptoNote::TransactionPrefix& transaction, size_t index); const TransactionOutput& getOutputChecked(const CryptoNote::TransactionPrefix& transaction, size_t index, TransactionTypes::OutputType type); diff --git a/cryptonote/src/Daemon/Daemon.cpp b/cryptonote/src/Daemon/Daemon.cpp index ed30be9..e54982b 100644 --- a/cryptonote/src/Daemon/Daemon.cpp +++ b/cryptonote/src/Daemon/Daemon.cpp @@ -1,4 +1,6 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2016-2018, The Karbo developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -73,6 +75,9 @@ namespace const command_line::arg_descriptor> arg_genesis_block_reward_address = { "genesis-block-reward-address", "" }; const command_line::arg_descriptor arg_blockexplorer_on = {"enable_blockexplorer", "Enable blockchain explorer RPC", false}; const command_line::arg_descriptor> arg_enable_cors = { "enable-cors", "Adds header 'Access-Control-Allow-Origin' to the daemon's RPC responses. Uses the value as domain. Use * for all" }; + const command_line::arg_descriptor arg_set_fee_address = { "fee-address", "Sets fee address for light wallets to the daemon's RPC responses.", "" }; + const command_line::arg_descriptor arg_set_view_key = { "view-key", "Sets private view key to check for masternode's fee.", "" }; + const command_line::arg_descriptor arg_set_collateral_hash = { "collateral-hash", "Sets collateral transaction hash for masternode.", "" }; const command_line::arg_descriptor arg_testnet_on = {"testnet", "Used to deploy test nets. Checkpoints and hardcoded seeds are ignored, " "network id is changed. Use it with --data-dir flag. The wallet must be launched with --testnet flag.", false}; const command_line::arg_descriptor arg_load_checkpoints = {"load-checkpoints", " Use builtin default checkpoints or checkpoint csv file for faster initial blockchain sync", ""}; @@ -174,6 +179,9 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_cmd_sett, arg_console); command_line::add_arg(desc_cmd_sett, arg_testnet_on); command_line::add_arg(desc_cmd_sett, arg_enable_cors); + command_line::add_arg(desc_cmd_sett, arg_set_fee_address); + command_line::add_arg(desc_cmd_sett, arg_set_view_key); + command_line::add_arg(desc_cmd_sett, arg_set_collateral_hash); command_line::add_arg(desc_cmd_sett, arg_blockexplorer_on); command_line::add_arg(desc_cmd_sett, arg_print_genesis_tx); command_line::add_arg(desc_cmd_sett, arg_genesis_block_reward_address); @@ -310,7 +318,7 @@ int main(int argc, char* argv[]) dbShutdownOnExit.cancel(); database.shutdown(); - database.destoy(dbConfig); + database.destroy(dbConfig); database.init(dbConfig); dbShutdownOnExit.resume(); @@ -350,7 +358,30 @@ int main(int argc, char* argv[]) logger(INFO) << "Starting core rpc server on address " << rpcConfig.getBindAddress(); rpcServer.start(rpcConfig.bindIp, rpcConfig.bindPort); -rpcServer.enableCors(command_line::get_arg(vm, arg_enable_cors)); + rpcServer.enableCors(command_line::get_arg(vm, arg_enable_cors)); + if (command_line::has_arg(vm, arg_set_fee_address)) { + std::string addr_str = command_line::get_arg(vm, arg_set_fee_address); + if (!addr_str.empty()) { + AccountPublicAddress acc = boost::value_initialized(); + if (!currency.parseAccountAddressString(addr_str, acc)) { + logger(ERROR, BRIGHT_RED) << "Bad fee address: " << addr_str; + return 1; + } + rpcServer.setFeeAddress(addr_str, acc); + } + } + if (command_line::has_arg(vm, arg_set_view_key)) { + std::string vk_str = command_line::get_arg(vm, arg_set_view_key); + if (!vk_str.empty()) { + rpcServer.setViewKey(vk_str); + } + } + if (command_line::has_arg(vm, arg_set_collateral_hash)) { + std::string ch_str = command_line::get_arg(vm, arg_set_collateral_hash); + if (!ch_str.empty()) { + rpcServer.setCollateralHash(ch_str); + } + } logger(INFO) << "Core rpc server started ok"; Tools::SignalHandler::install([&dch, &p2psrv] { diff --git a/cryptonote/src/Daemon/DaemonCommandsHandler.cpp b/cryptonote/src/Daemon/DaemonCommandsHandler.cpp index c601598..e19ce1e 100644 --- a/cryptonote/src/Daemon/DaemonCommandsHandler.cpp +++ b/cryptonote/src/Daemon/DaemonCommandsHandler.cpp @@ -262,14 +262,14 @@ bool DaemonCommandsHandler::print_alternate_chains(const std::vector m_core.getTopBlockIndex()) { - std::cout << "block wasn't found. Current block chain height: " << m_core.getTopBlockIndex() + 1 << ", requested: " << height << std::endl; + if (height > m_core.getTopBlockIndex()) { + std::cout << "block wasn't found. Current block chain height: " << m_core.getTopBlockIndex() << ", requested: " << height << std::endl; return false; } - auto hash = m_core.getBlockHashByIndex(height - 1); + auto hash = m_core.getBlockHashByIndex(height); std::cout << "block_id: " << hash << ENDL; - print_as_json(m_core.getBlockByIndex(height - 1)); + print_as_json(m_core.getBlockByIndex(height)); return true; } diff --git a/cryptonote/src/InProcessNode/InProcessNode.cpp b/cryptonote/src/InProcessNode/InProcessNode.cpp index b1fc3d8..8f87a76 100644 --- a/cryptonote/src/InProcessNode/InProcessNode.cpp +++ b/cryptonote/src/InProcessNode/InProcessNode.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -551,6 +552,14 @@ BlockHeaderInfo InProcessNode::getLastLocalBlockHeaderInfo() const { return lastLocalBlockHeaderInfo; } +std::string InProcessNode::getLastFeeAddress() const { + return ""; +} + +std::string InProcessNode::getLastCollateralHash() const { + return ""; +} + void InProcessNode::getBlockHashesByTimestamps(uint64_t timestampBegin, size_t secondsCount, std::vector& blockHashes, const Callback& callback) { std::unique_lock lock(mutex); if (state != INITIALIZED) { @@ -887,6 +896,16 @@ std::error_code InProcessNode::doGetTransactions(const std::vector return std::error_code(); } +void InProcessNode::getFeeAddress(std::string& feeAddress, const Callback& callback) { + feeAddress = ""; + callback({}); +} + +void InProcessNode::getCollateralHash(std::string& collateralHash, const Callback &callback) { + collateralHash = ""; + callback({}); +} + void InProcessNode::isSynchronized(bool& syncStatus, const Callback& callback) { std::unique_lock lock(mutex); if (state != INITIALIZED) { diff --git a/cryptonote/src/InProcessNode/InProcessNode.h b/cryptonote/src/InProcessNode/InProcessNode.h index f8355f8..c3b387f 100644 --- a/cryptonote/src/InProcessNode/InProcessNode.h +++ b/cryptonote/src/InProcessNode/InProcessNode.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -66,6 +67,8 @@ class InProcessNode : public INode, public CryptoNote::ICryptoNoteProtocolObserv virtual uint32_t getLocalBlockCount() const override; virtual uint32_t getKnownBlockCount() const override; virtual uint64_t getLastLocalBlockTimestamp() const override; + virtual std::string getLastFeeAddress() const override; + virtual std::string getLastCollateralHash() const override; virtual void getBlockHashesByTimestamps(uint64_t timestampBegin, size_t secondsCount, std::vector& blockHashes, const Callback& callback) override; virtual void getTransactionHashesByPaymentId(const Crypto::Hash& paymentId, std::vector& transactionHashes, const Callback& callback) override; @@ -86,6 +89,8 @@ class InProcessNode : public INode, public CryptoNote::ICryptoNoteProtocolObserv virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; virtual void getBlock(const uint32_t blockHeight, BlockDetails &block, const Callback& callback) override; virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; + virtual void getFeeAddress(std::string& feeAddress, const Callback& callback) override; + virtual void getCollateralHash(std::string &collateralHash, const Callback& callback) override; virtual void isSynchronized(bool& syncStatus, const Callback& callback) override; private: diff --git a/cryptonote/src/NodeRpcProxy/NodeRpcProxy.cpp b/cryptonote/src/NodeRpcProxy/NodeRpcProxy.cpp index bad2ef6..3155da6 100644 --- a/cryptonote/src/NodeRpcProxy/NodeRpcProxy.cpp +++ b/cryptonote/src/NodeRpcProxy/NodeRpcProxy.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -95,6 +96,7 @@ void NodeRpcProxy::resetInternalState() { lastLocalBlockHeaderInfo.difficulty = 0; lastLocalBlockHeaderInfo.reward = 0; m_knownTxs.clear(); + m_feeaddress = ""; } void NodeRpcProxy::init(const INode::Callback& callback) { @@ -141,6 +143,18 @@ bool NodeRpcProxy::shutdown() { return true; } +void NodeRpcProxy::feeAddressCallback(std::error_code ec) { + if (ec) { + m_feeaddress = ""; + } +} + +void NodeRpcProxy::collateralHashCallback(std::error_code ec) { + if (ec) { + m_collateralhash = ""; + } +} + void NodeRpcProxy::workerThread(const INode::Callback& initialized_callback) { try { Dispatcher dispatcher; @@ -160,6 +174,16 @@ void NodeRpcProxy::workerThread(const INode::Callback& initialized_callback) { m_cv_initialized.notify_all(); } + { + std::error_code ec; + getFeeAddress(m_feeaddress, std::bind(&NodeRpcProxy::feeAddressCallback, this, ec)); + } + + { + std::error_code ec; + getCollateralHash(m_collateralhash, std::bind(&NodeRpcProxy::collateralHashCallback, this, ec)); + } + updateNodeStatus(); initialized_callback(std::error_code()); @@ -347,6 +371,16 @@ BlockHeaderInfo NodeRpcProxy::getLastLocalBlockHeaderInfo() const { return lastLocalBlockHeaderInfo; } +std::string NodeRpcProxy::getLastFeeAddress() const { + std::lock_guard lock(m_mutex); + return m_feeaddress; +} + +std::string NodeRpcProxy::getLastCollateralHash() const { + std::lock_guard lock(m_mutex); + return m_collateralhash; +} + void NodeRpcProxy::getBlockHashesByTimestamps(uint64_t timestampBegin, size_t secondsCount, std::vector& blockHashes, const Callback& callback) { std::lock_guard lock(m_mutex); if (m_state != STATE_INITIALIZED) { @@ -497,6 +531,26 @@ void NodeRpcProxy::getTransactions(const std::vector& transactionH scheduleRequest(std::bind(&NodeRpcProxy::doGetTransactions, this, std::cref(transactionHashes), std::ref(transactions)), callback); } +void NodeRpcProxy::getFeeAddress(std::string &feeAddress, const Callback& callback) { + std::lock_guard lock(m_mutex); + if (m_state != STATE_INITIALIZED) { + callback(make_error_code(error::NOT_INITIALIZED)); + return; + } + + scheduleRequest(std::bind(&NodeRpcProxy::doGetFeeAddress, this, std::ref(feeAddress)), callback); +} + +void NodeRpcProxy::getCollateralHash(std::string &collateralHash, const Callback& callback) { + std::lock_guard lock(m_mutex); + if (m_state != STATE_INITIALIZED) { + callback(make_error_code(error::NOT_INITIALIZED)); + return; + } + + scheduleRequest(std::bind(&NodeRpcProxy::doGetCollateralHash, this, std::ref(collateralHash)), callback); +} + void NodeRpcProxy::isSynchronized(bool& syncStatus, const Callback& callback) { std::lock_guard lock(m_mutex); if (m_state != STATE_INITIALIZED) { @@ -715,6 +769,32 @@ std::error_code NodeRpcProxy::doGetTransactions(const std::vector& return ec; } +std::error_code NodeRpcProxy::doGetFeeAddress(std::string& feeAddress) { + COMMAND_RPC_GET_FEE_ADDRESS::request req = AUTO_VAL_INIT(req); + COMMAND_RPC_GET_FEE_ADDRESS::response resp = AUTO_VAL_INIT(resp); + + std::error_code ec = jsonCommand("/feeaddress", req, resp); + if (ec) { + return ec; + } + + feeAddress = std::move(resp.fee_address); + return ec; +} + +std::error_code NodeRpcProxy::doGetCollateralHash(std::string& collateralHash) { + COMMAND_RPC_GET_COLLATERAL_HASH::request req = AUTO_VAL_INIT(req); + COMMAND_RPC_GET_COLLATERAL_HASH::response resp = AUTO_VAL_INIT(resp); + + std::error_code ec = jsonCommand("/collateralhash", req, resp); + if (ec) { + return ec; + } + + collateralHash = std::move(resp.collateralHash); + return ec; +} + void NodeRpcProxy::scheduleRequest(std::function&& procedure, const Callback& callback) { // callback is located on stack, so copy it inside binder class Wrapper { diff --git a/cryptonote/src/NodeRpcProxy/NodeRpcProxy.h b/cryptonote/src/NodeRpcProxy/NodeRpcProxy.h index c3474ee..5ac4170 100644 --- a/cryptonote/src/NodeRpcProxy/NodeRpcProxy.h +++ b/cryptonote/src/NodeRpcProxy/NodeRpcProxy.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -64,6 +65,8 @@ class NodeRpcProxy : public CryptoNote::INode { virtual uint32_t getLocalBlockCount() const override; virtual uint32_t getKnownBlockCount() const override; virtual uint64_t getLastLocalBlockTimestamp() const override; + virtual std::string getLastFeeAddress() const override; + virtual std::string getLastCollateralHash() const override; virtual void getBlockHashesByTimestamps(uint64_t timestampBegin, size_t secondsCount, std::vector& blockHashes, const Callback& callback) override; virtual void getTransactionHashesByPaymentId(const Crypto::Hash& paymentId, std::vector& transactionHashes, const Callback& callback) override; @@ -81,6 +84,8 @@ class NodeRpcProxy : public CryptoNote::INode { virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; virtual void getBlock(const uint32_t blockHeight, BlockDetails &block, const Callback& callback) override; virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; + virtual void getFeeAddress(std::string& feeAddress, const Callback& callback) override; + virtual void getCollateralHash(std::string &collateralHash, const Callback& callback) override; virtual void isSynchronized(bool& syncStatus, const Callback& callback) override; unsigned int rpcTimeout() const { return m_rpcTimeout; } @@ -114,6 +119,8 @@ class NodeRpcProxy : public CryptoNote::INode { std::error_code doGetBlock(const uint32_t blockHeight, BlockDetails& block); std::error_code doGetTransactionHashesByPaymentId(const Crypto::Hash& paymentId, std::vector& transactionHashes); std::error_code doGetTransactions(const std::vector& transactionHashes, std::vector& transactions); + std::error_code doGetFeeAddress(std::string& feeAddress); + std::error_code doGetCollateralHash(std::string& collateralHash); void scheduleRequest(std::function&& procedure, const Callback& callback); template @@ -157,6 +164,10 @@ class NodeRpcProxy : public CryptoNote::INode { //protect it with mutex if decided to add worker threads std::unordered_set m_knownTxs; + void feeAddressCallback(std::error_code ec); + void collateralHashCallback(std::error_code ec); + std::string m_feeaddress, m_collateralhash; + bool m_connected; }; } diff --git a/cryptonote/src/PaymentGate/NodeFactory.cpp b/cryptonote/src/PaymentGate/NodeFactory.cpp index df55d1d..e8b8caa 100644 --- a/cryptonote/src/PaymentGate/NodeFactory.cpp +++ b/cryptonote/src/PaymentGate/NodeFactory.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -38,6 +39,8 @@ class NodeRpcStub: public CryptoNote::INode { virtual uint32_t getLocalBlockCount() const override { return 0; } virtual uint32_t getKnownBlockCount() const override { return 0; } virtual uint64_t getLastLocalBlockTimestamp() const override { return 0; } + virtual std::string getLastFeeAddress() const override { return ""; } + virtual std::string getLastCollateralHash() const override { return ""; } virtual void getBlockHashesByTimestamps(uint64_t timestampBegin, size_t secondsCount, std::vector& blockHashes, const Callback& callback) override { callback(std::error_code()); @@ -83,6 +86,10 @@ class NodeRpcStub: public CryptoNote::INode { virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override { } + virtual void getFeeAddress(std::string& feeAddress, const Callback& callback) override { } + + virtual void getCollateralHash(std::string& collateralHash, const Callback& callback) override { } + virtual void isSynchronized(bool& syncStatus, const Callback& callback) override { } }; diff --git a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp index a626a9e..ecdd380 100644 --- a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp +++ b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp @@ -42,6 +42,19 @@ void Reset::Request::serialize(CryptoNote::ISerializer& serializer) { void Reset::Response::serialize(CryptoNote::ISerializer& serializer) { } +void ChangePassword::Request::serialize(CryptoNote::ISerializer& serializer) { + bool hasOldPassword = serializer(oldPassword, "oldPassword"); + bool hasNewPassword = serializer(newPassword, "newPassword"); + + if (!hasOldPassword || !hasNewPassword) { + throw RequestSerializationError(); + } +} + +void ChangePassword::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(status, "status"); +} + void GetViewKey::Request::serialize(CryptoNote::ISerializer& serializer) { } diff --git a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.h b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.h index 8e2911f..c0e8ae6 100644 --- a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.h +++ b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcMessages.h @@ -66,6 +66,21 @@ struct Reset { }; }; +struct ChangePassword { + struct Request { + std::string oldPassword; + std::string newPassword; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::string status; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + struct GetViewKey { struct Request { void serialize(CryptoNote::ISerializer& serializer); diff --git a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.cpp b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.cpp index ce6c89a..1109652 100644 --- a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.cpp +++ b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.cpp @@ -37,6 +37,7 @@ PaymentServiceJsonRpcServer::PaymentServiceJsonRpcServer(System::Dispatcher& sys handlers.emplace("save", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleSave, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("export", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleExport, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("reset", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleReset, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("changePassword", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleChangePassword, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("createAddress", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleCreateAddress, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("createAddressList", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleCreateAddressList, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("deleteAddress", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleDeleteAddress, this, std::placeholders::_1, std::placeholders::_2))); @@ -132,6 +133,10 @@ std::error_code PaymentServiceJsonRpcServer::handleReset(const Reset::Request& r } } +std::error_code PaymentServiceJsonRpcServer::handleChangePassword(const ChangePassword::Request& request, ChangePassword::Response& response) { + return service.changePassword(request.oldPassword, request.newPassword, response.status); +} + std::error_code PaymentServiceJsonRpcServer::handleCreateAddress(const CreateAddress::Request& request, CreateAddress::Response& response) { if (request.spendSecretKey.empty() && request.spendPublicKey.empty()) { return service.createAddress(response.address); diff --git a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.h b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.h index 2d3a2b5..4d47032 100644 --- a/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.h +++ b/cryptonote/src/PaymentGate/PaymentServiceJsonRpcServer.h @@ -74,6 +74,7 @@ class PaymentServiceJsonRpcServer : public CryptoNote::JsonRpcServer { std::error_code handleSave(const Save::Request& request, Save::Response& response); std::error_code handleExport(const Export::Request& request, Export::Response& response); std::error_code handleReset(const Reset::Request& request, Reset::Response& response); + std::error_code handleChangePassword(const ChangePassword::Request& request, ChangePassword::Response& response); std::error_code handleCreateAddress(const CreateAddress::Request& request, CreateAddress::Response& response); std::error_code handleCreateAddressList(const CreateAddressList::Request& request, CreateAddressList::Response& response); std::error_code handleDeleteAddress(const DeleteAddress::Request& request, DeleteAddress::Response& response); diff --git a/cryptonote/src/PaymentGate/WalletService.cpp b/cryptonote/src/PaymentGate/WalletService.cpp index 0c78a03..8275bfa 100644 --- a/cryptonote/src/PaymentGate/WalletService.cpp +++ b/cryptonote/src/PaymentGate/WalletService.cpp @@ -515,6 +515,31 @@ std::error_code WalletService::resetWallet() { return std::error_code(); } +std::error_code WalletService::changePassword(const std::string &oldPassword, const std::string &newPassword, std::string &status) { + try { + System::EventLock lk(readyEvent); + + if (!inited) { + logger(Logging::WARNING, Logging::BRIGHT_YELLOW) << "Password change impossible: Wallet Service is not initialized"; + return make_error_code(CryptoNote::error::NOT_INITIALIZED); + } + + wallet.changePassword(oldPassword, newPassword); + wallet.save(); // Save wallet file to actually update the password in wallet file + status = "OK"; + logger(Logging::INFO, Logging::BRIGHT_WHITE) << "Wallet password was changed successfully"; + return std::error_code(); + } catch (std::system_error& x) { + logger(Logging::WARNING, Logging::BRIGHT_YELLOW) << "Error while changing password: " << x.what(); + status = x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::INFO, Logging::BRIGHT_WHITE) << "Error while changing password: " << x.what(); + status = x.what(); + return make_error_code(CryptoNote::error::WRONG_PASSWORD); + } +} + std::error_code WalletService::replaceWithNewWallet(const std::string& viewSecretKeyText) { try { System::EventLock lk(readyEvent); @@ -1209,7 +1234,7 @@ void WalletService::replaceWithNewWallet(const Crypto::SecretKey& viewSecretKey) if (!boost::filesystem::exists(backup)) { boost::filesystem::rename(config.walletFile, backup); - logger(Logging::DEBUGGING) << "Walled file '" << config.walletFile << "' backed up to '" << backup << '\''; + logger(Logging::DEBUGGING) << "Wallet file '" << config.walletFile << "' backed up to '" << backup << '\''; break; } } diff --git a/cryptonote/src/PaymentGate/WalletService.h b/cryptonote/src/PaymentGate/WalletService.h index 1918b86..b8a9e60 100644 --- a/cryptonote/src/PaymentGate/WalletService.h +++ b/cryptonote/src/PaymentGate/WalletService.h @@ -64,6 +64,7 @@ class WalletService { std::error_code saveWalletNoThrow(); std::error_code exportWallet(const std::string& fileName); std::error_code resetWallet(); + std::error_code changePassword(const std::string &oldPassword, const std::string &newPassword, std::string &status); std::error_code replaceWithNewWallet(const std::string& viewSecretKey); std::error_code createAddress(const std::string& spendSecretKeyText, std::string& address); std::error_code createAddressList(const std::vector& spendSecretKeysText, std::vector& addresses); diff --git a/cryptonote/src/PaymentGateService/PaymentGateService.cpp b/cryptonote/src/PaymentGateService/PaymentGateService.cpp index 45cea0f..cb94c36 100644 --- a/cryptonote/src/PaymentGateService/PaymentGateService.cpp +++ b/cryptonote/src/PaymentGateService/PaymentGateService.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -189,7 +190,7 @@ void PaymentGateService::runInProcess(Logging::LoggerRef& log) { dbShutdownOnExit.cancel(); database.shutdown(); - database.destoy(dbConfig); + database.destroy(dbConfig); database.init(dbConfig); dbShutdownOnExit.resume(); diff --git a/cryptonote/src/PaymentGateService/RpcNodeConfiguration.cpp b/cryptonote/src/PaymentGateService/RpcNodeConfiguration.cpp index 3d5246b..382b17c 100644 --- a/cryptonote/src/PaymentGateService/RpcNodeConfiguration.cpp +++ b/cryptonote/src/PaymentGateService/RpcNodeConfiguration.cpp @@ -28,8 +28,8 @@ RpcNodeConfiguration::RpcNodeConfiguration() { void RpcNodeConfiguration::initOptions(boost::program_options::options_description& desc) { desc.add_options() - ("daemon-address", po::value()->default_value("localhost"), "PinkstarcoinV2d address") - ("daemon-port", po::value()->default_value(39984), "daemon port"); + ("daemon-address", po::value()->default_value("localhost"), "Bittoriumd address") + ("daemon-port", po::value()->default_value(34916), "daemon port"); } void RpcNodeConfiguration::init(const boost::program_options::variables_map& options) { diff --git a/cryptonote/src/PaymentGateService/main.cpp b/cryptonote/src/PaymentGateService/main.cpp index 9cb3ff7..aaf33f5 100644 --- a/cryptonote/src/PaymentGateService/main.cpp +++ b/cryptonote/src/PaymentGateService/main.cpp @@ -304,7 +304,7 @@ int main(int argc, char** argv) { return 0; //help message requested or so } - Logging::LoggerRef(pg.getLogger(), "main")(Logging::INFO) << "walled v" << PROJECT_VERSION_LONG; + Logging::LoggerRef(pg.getLogger(), "main")(Logging::INFO) << "walletd v" << PROJECT_VERSION_LONG; const auto& config = pg.getConfig(); diff --git a/cryptonote/src/Rpc/CoreRpcServerCommandsDefinitions.h b/cryptonote/src/Rpc/CoreRpcServerCommandsDefinitions.h index b9e7065..a0b1d80 100644 --- a/cryptonote/src/Rpc/CoreRpcServerCommandsDefinitions.h +++ b/cryptonote/src/Rpc/CoreRpcServerCommandsDefinitions.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2017-2018, The Karbo developers // // This file is part of Bytecoin. // @@ -286,6 +287,7 @@ struct COMMAND_RPC_GET_INFO { uint32_t hashrate; std::string version; bool synced; + std::string fee_address; void serialize(ISerializer &s) { KV_MEMBER(status) @@ -303,6 +305,7 @@ struct COMMAND_RPC_GET_INFO { KV_MEMBER(hashrate) KV_MEMBER(synced) KV_MEMBER(version) + KV_MEMBER(fee_address) } }; }; @@ -319,6 +322,21 @@ struct COMMAND_RPC_STOP_DAEMON { typedef STATUS_STRUCT response; }; +//----------------------------------------------- +struct COMMAND_RPC_GET_FEE_ADDRESS { + typedef EMPTY_STRUCT request; + + struct response { + std::string fee_address; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(fee_address) + KV_MEMBER(status) + } + }; +}; + // struct COMMAND_RPC_GETBLOCKCOUNT { typedef std::vector request; @@ -895,4 +913,42 @@ struct COMMAND_RPC_GET_ISSUED_COINS { } }; }; + +struct COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT { + struct request { + std::string transaction; + std::string account; + std::string viewKey; + + void serialize(ISerializer &s) { + KV_MEMBER(transaction) + KV_MEMBER(account) + KV_MEMBER(viewKey) + } + }; + + struct response { + uint64_t amount; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(amount) + KV_MEMBER(status) + } + }; +}; + +struct COMMAND_RPC_GET_COLLATERAL_HASH { + typedef EMPTY_STRUCT request; + + struct response { + std::string collateralHash; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(collateralHash) + KV_MEMBER(status) + } + }; +}; } diff --git a/cryptonote/src/Rpc/RpcServer.cpp b/cryptonote/src/Rpc/RpcServer.cpp index bec0bba..7982f16 100644 --- a/cryptonote/src/Rpc/RpcServer.cpp +++ b/cryptonote/src/Rpc/RpcServer.cpp @@ -1,4 +1,6 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2016-2018, The Karbowanec developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -22,10 +24,12 @@ // CryptoNote #include "Common/StringTools.h" +#include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/CryptoNoteTools.h" #include "CryptoNoteCore/Core.h" #include "CryptoNoteCore/Miner.h" #include "CryptoNoteCore/TransactionExtra.h" +#include "CryptoNoteCore/TransactionUtils.h" #include "CryptoNoteConfig.h" #include "CryptoNoteProtocol/CryptoNoteProtocolHandlerCommon.h" #include "P2p/NetNode.h" @@ -128,10 +132,13 @@ std::unordered_map(&RpcServer::on_get_height), true } }, { "/gettransactions", { jsonMethod(&RpcServer::on_get_transactions), false } }, { "/sendrawtransaction", { jsonMethod(&RpcServer::on_send_raw_tx), false } }, + { "/feeaddress", { jsonMethod(&RpcServer::on_get_fee_address), true } }, + { "/collateralhash", { jsonMethod(&RpcServer::on_get_collateral_hash), true } }, { "/stop_daemon", { jsonMethod(&RpcServer::on_stop_daemon), true } }, { "/getpeers", { jsonMethod(&RpcServer::on_get_peers), true } }, { "/getpeersgray", { jsonMethod(&RpcServer::on_get_peersgray), true } }, { "/get_generated_coins", { jsonMethod(&RpcServer::on_get_issued), true } }, + { "/get_amounts_for_account", { jsonMethod(&RpcServer::on_get_transaction_out_amounts_for_account), true } }, // json rpc { "/json_rpc", { std::bind(&RpcServer::processJsonRpcRequest, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), true } } @@ -228,10 +235,79 @@ std::vector RpcServer::getCorsDomains() { return m_cors_domains; } +bool RpcServer::setFeeAddress(const std::string& fee_address, const AccountPublicAddress& fee_acc) { + logger(INFO) << "Masternode fee address: " << fee_address; + m_fee_address = fee_address; + m_fee_acc = fee_acc; + return true; +} + +bool RpcServer::setViewKey(const std::string& view_key) { + Crypto::Hash private_view_key_hash; + size_t size; + if (!Common::fromHex(view_key, &private_view_key_hash, sizeof(private_view_key_hash), size) || size != sizeof(private_view_key_hash)) { + logger(INFO) << "Could not parse private view key"; + return false; + } + logger(INFO) << "Masternode view key: " << view_key; + m_view_key = *(struct Crypto::SecretKey *) &private_view_key_hash; + return true; +} + +bool RpcServer::setCollateralHash(const std::string& collateral_hash) { + size_t size; + if (!Common::fromHex(collateral_hash, &m_collateral_hash, sizeof(m_collateral_hash), size) || size != sizeof(Crypto::Hash)) { + logger(INFO) << "Could not parse transaction hash"; + return false; + } + return true; +} + bool RpcServer::isCoreReady() { return m_core.getCurrency().isTestnet() || m_p2p.get_payload_object().isSynchronized(); } +bool RpcServer::masternode_check_incoming_tx(const BinaryArray& tx_blob) { + Crypto::Hash tx_hash = NULL_HASH; + Crypto::Hash tx_prefixt_hash = NULL_HASH; + Transaction tx; + if (!parseAndValidateTransactionFromBinaryArray(tx_blob, tx, tx_hash, tx_prefixt_hash)) { + logger(INFO) << "Could not parse tx from blob"; + return false; + } + CryptoNote::TransactionPrefix transaction = *static_cast(&tx); + + // Check if this is a fusion transaction + uint64_t inAmount = 0, outAmount = 0; + for (auto in : tx.inputs) { + inAmount += CryptoNote::getTransactionInputAmount(in); + } + + for (auto out : tx.outputs) { + outAmount += CryptoNote::getTransactionOutputAmount(out); + } + + if (inAmount == outAmount) { + logger(INFO) << "Masternode received fusion transaction, relaying with no fee check."; + return true; + } + + // Check for outputs to masternode's wallet address + std::vector out; + uint64_t amount; + + if (!CryptoNote::findOutputsToAccount(transaction, m_fee_acc, m_view_key, out, amount)) { + logger(INFO) << "Could not find outputs to masternode fee address"; + return false; + } + + if (amount != 0) { + logger(INFO) << "Masternode received relayed transaction fee: " << m_core.getCurrency().formatAmount(amount) << " BTOR"; + return true; + } + return false; +} + // // Binary handlers // @@ -535,6 +611,14 @@ bool RpcServer::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMM Crypto::Hash transactionHash = Crypto::cn_fast_hash(transactions.back().data(), transactions.back().size()); logger(DEBUGGING) << "transaction " << transactionHash << " came in on_send_raw_tx"; + if (!m_fee_address.empty() && m_view_key != NULL_SECRET_KEY) { + if (!masternode_check_incoming_tx(transactions.back())) { + logger(INFO) << "Transaction not relayed due to lack of masternode fee"; + res.status = "Not relayed due to lack of node fee"; + return true; + } + } + if (!m_core.addTransactionToPool(transactions.back())) { logger(DEBUGGING) << "[on_send_raw_tx]: tx verification failed"; res.status = "Failed"; @@ -559,6 +643,102 @@ bool RpcServer::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMM return true; } +bool RpcServer::on_get_fee_address(const COMMAND_RPC_GET_FEE_ADDRESS::request& req, COMMAND_RPC_GET_FEE_ADDRESS::response& res) { + if (m_fee_address.empty()) { + res.status = CORE_RPC_STATUS_OK; + return false; + } + if (!verifyCollateral()) { + res.status = "Collateral not locked!"; + return false; + } + res.fee_address = m_fee_address; + res.status = CORE_RPC_STATUS_OK; + return true; +} + +bool RpcServer::verifyCollateral() { + COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT::request req; + COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT::response res; + if (m_collateral_hash == NULL_HASH) { + return false; + } + req.transaction = Common::toHex(&m_collateral_hash, sizeof(m_collateral_hash)); + req.account = "bTXQBcHwS83gk5Ucb7gS9h58yMR7yw5rDjCNP22BT9DYjRdY6yxa9SHA1UALacBPpBTvirC4VY6n1JEJAGewV3g82SctDmvTw"; + req.viewKey = "d3365d5799225af5954e5b938b3c4703335151dfc339b8bb608d79d2a376890d"; + if (on_get_transaction_out_amounts_for_account(req, res) && res.amount == 7500000) { + return true; + } + return false; +} + +bool RpcServer::on_get_transaction_out_amounts_for_account(const COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT::request& req, COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT::response& res) +{ + Crypto::Hash tx_hash = NULL_HASH, tx_prefixt_hash = NULL_HASH; + AccountPublicAddress acc = boost::value_initialized(); + Crypto::SecretKey viewKey; + Transaction tx; + TransactionPrefix transactionPrefix; + std::vector tx_hashes, missed_txs; + std::vector tx_blobs; + std::vector out; + uint64_t amount; + + if (!podFromHex(req.transaction, tx_hash)) { + res.status = "Invalid transaction hash!"; + return false; + } + + if (!req.account.empty()) { + if (!m_core.getCurrency().parseAccountAddressString(req.account, acc)) { + res.status = "Bad wallet address!"; + return false; + } + } + + if (!podFromHex(req.viewKey, viewKey)) { + res.status = "Invalid view key!"; + return false; + } + + if (!m_core.hasTransaction(tx_hash)) { + res.status = "Transaction not found!"; + return false; + } + + tx_hashes.push_back(tx_hash); + m_core.getTransactions(tx_hashes, tx_blobs, missed_txs); + + if (!parseAndValidateTransactionFromBinaryArray(tx_blobs.front(), tx, tx_hash, tx_prefixt_hash)) { + res.status = "Could not parse transaction from blob"; + return false; + } + + // Check for outputs to wallet address + + transactionPrefix = *static_cast(&tx); + + if (!CryptoNote::findOutputsToAccount(transactionPrefix, acc, viewKey, out, amount)) { + logger(INFO) << "Could not find outputs to wallet address"; + return false; + } + + res.amount = amount; + res.status = CORE_RPC_STATUS_OK; + return true; +} + +bool RpcServer::on_get_collateral_hash(const COMMAND_RPC_GET_COLLATERAL_HASH::request& req, COMMAND_RPC_GET_COLLATERAL_HASH::response& res) { + if (m_collateral_hash != NULL_HASH) { + res.collateralHash = Common::toHex(&m_collateral_hash, sizeof(m_collateral_hash)); + res.status = CORE_RPC_STATUS_OK; + return true; + } + res.status = "Collateral hash not set or invalid."; + return false; +} + + bool RpcServer::on_get_peers(const COMMAND_RPC_GET_PEERS::request& req, COMMAND_RPC_GET_PEERS::response& res) { std::list peers_white; diff --git a/cryptonote/src/Rpc/RpcServer.h b/cryptonote/src/Rpc/RpcServer.h index 94353e5..2a1efc6 100644 --- a/cryptonote/src/Rpc/RpcServer.h +++ b/cryptonote/src/Rpc/RpcServer.h @@ -1,4 +1,6 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2016-2018, The Karbowanec developers +// Copyright (c) 2018, The Bittorium developers // // This file is part of Bytecoin. // @@ -41,6 +43,11 @@ class RpcServer : public HttpServer { bool enableCors(const std::vector domains); std::vector getCorsDomains(); + bool setFeeAddress(const std::string& fee_address, const AccountPublicAddress& fee_acc); + bool setViewKey(const std::string& view_key); + bool setCollateralHash(const std::string& collateral_hash); + bool masternode_check_incoming_tx(const BinaryArray& tx_blob); + bool on_get_block_headers_range(const COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::request& req, COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response& res, JsonRpc::JsonRpcError& error_resp); bool on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request& req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response& res); @@ -58,6 +65,7 @@ class RpcServer : public HttpServer { virtual void processRequest(const HttpRequest& request, HttpResponse& response) override; bool processJsonRpcRequest(const HttpRequest& request, HttpResponse& response); bool isCoreReady(); + bool verifyCollateral(); // binary handlers bool on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res); @@ -82,6 +90,9 @@ class RpcServer : public HttpServer { bool on_get_peers(const COMMAND_RPC_GET_PEERS::request& req, COMMAND_RPC_GET_PEERS::response& res); bool on_get_peersgray(const COMMAND_RPC_GET_PEERSGRAY::request& req, COMMAND_RPC_GET_PEERSGRAY::response& res); bool on_get_issued(const COMMAND_RPC_GET_ISSUED_COINS::request& req, COMMAND_RPC_GET_ISSUED_COINS::response& res); + bool on_get_fee_address(const COMMAND_RPC_GET_FEE_ADDRESS::request& req, COMMAND_RPC_GET_FEE_ADDRESS::response& res); + bool on_get_transaction_out_amounts_for_account(const COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT::request& req, COMMAND_RPC_GET_TRANSACTION_OUT_AMOUNTS_FOR_ACCOUNT::response& res); + bool on_get_collateral_hash(const COMMAND_RPC_GET_COLLATERAL_HASH::request& req, COMMAND_RPC_GET_COLLATERAL_HASH::response& res); // json rpc bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res); @@ -105,7 +116,11 @@ class RpcServer : public HttpServer { Core& m_core; NodeServer& m_p2p; ICryptoNoteProtocolHandler& m_protocol; -std::vector m_cors_domains; + std::vector m_cors_domains; + std::string m_fee_address; + Crypto::SecretKey m_view_key = NULL_SECRET_KEY; + Crypto::Hash m_collateral_hash = NULL_HASH; + AccountPublicAddress m_fee_acc; }; } diff --git a/cryptonote/src/SimpleWallet/PasswordContainer.cpp b/cryptonote/src/SimpleWallet/PasswordContainer.cpp index 0502979..b4e2d7c 100644 --- a/cryptonote/src/SimpleWallet/PasswordContainer.cpp +++ b/cryptonote/src/SimpleWallet/PasswordContainer.cpp @@ -75,10 +75,18 @@ namespace Tools return read_password(false); } + bool PasswordContainer::read_password(const std::string &message) { + return read_password(false, message); + } + bool PasswordContainer::read_and_validate() { + return read_and_validate("Give your new wallet a password: "); + } + + bool PasswordContainer::read_and_validate(const std::string &message) { std::string tmpPassword = m_password; - if (!read_password()) { + if (!read_password(message)) { std::cout << "Failed to read password!"; return false; } @@ -91,15 +99,15 @@ namespace Tools } bool PasswordContainer::read_password(bool verify) { + return read_password(verify, verify ? "Give your new wallet a password: " : "Enter password: "); + } + + bool PasswordContainer::read_password(bool verify, const std::string &message) { clear(); bool r; if (is_cin_tty()) { - if (verify) { - std::cout << "Give your new wallet a password: "; - } else { - std::cout << "Enter password: "; - } + std::cout << message; if (verify) { std::string password1; std::string password2; @@ -111,16 +119,16 @@ namespace Tools if (password1 == password2) { m_password = std::move(password2); m_empty = false; - return true; + return true; } else { std::cout << "Passwords do not match, try again." << std::endl; clear(); - return read_password(true); + return read_password(true); } } - } + } } else { - r = read_from_tty(m_password); + r = read_from_tty(m_password); } } else { r = read_from_file(); diff --git a/cryptonote/src/SimpleWallet/PasswordContainer.h b/cryptonote/src/SimpleWallet/PasswordContainer.h index 80c9367..3f7ce56 100644 --- a/cryptonote/src/SimpleWallet/PasswordContainer.h +++ b/cryptonote/src/SimpleWallet/PasswordContainer.h @@ -37,8 +37,11 @@ namespace Tools void password(std::string&& val) { m_password = std::move(val); m_empty = false; } bool read_and_validate(); + bool read_and_validate(const std::string &message); bool read_password(); + bool read_password(const std::string &message); bool read_password(bool verify); + bool read_password(bool verify, const std::string &message); private: bool read_from_file(); diff --git a/cryptonote/src/SimpleWallet/SimpleWallet.cpp b/cryptonote/src/SimpleWallet/SimpleWallet.cpp index 1c693eb..d00e8d2 100644 --- a/cryptonote/src/SimpleWallet/SimpleWallet.cpp +++ b/cryptonote/src/SimpleWallet/SimpleWallet.cpp @@ -2,6 +2,8 @@ Copyright (C) 2018, The TurtleCoin developers Copyright (C) 2018, The PinkstarcoinV2 developers Copyright (C) 2018, The Bittorium developers +Copyright (c) 2018, The Karbo developers + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,6 +20,13 @@ along with this program. If not, see . */ #include +#include + +#include "Common/JsonValue.h" +#include "Rpc/HttpClient.h" + +// Fee address is declared here so we can access it from other source files +std::string remote_fee_address; int main(int argc, char **argv) { @@ -56,6 +65,8 @@ int main(int argc, char **argv) System::Dispatcher localDispatcher; System::Dispatcher *dispatcher = &localDispatcher; + remote_fee_address = getFeeAddress(localDispatcher, config.host, config.port); + /* Our connection to Bittoriumd */ std::unique_ptr node( new CryptoNote::NodeRpcProxy(config.host, config.port, @@ -928,6 +939,10 @@ void inputLoop(std::shared_ptr &walletInfo, CryptoNote::INode &node) { reset(node, walletInfo); } + else if (words[0] == "change_password") { + words.erase(words.begin()); + changePassword(walletInfo, words); + } else if (!walletInfo->viewWallet) { if (command == "outgoing_transfers") @@ -997,7 +1012,9 @@ void help(bool viewWallet) << SuccessMsg("save", 25) << "Save your wallet state" << std::endl << SuccessMsg("incoming_transfers", 25) - << "Show incoming transfers" << std::endl; + << "Show incoming transfers" << std::endl + << SuccessMsg("change_password", 25) + << "Change password of current wallet file" << std::endl; if (viewWallet) { @@ -1385,6 +1402,56 @@ void reset(CryptoNote::INode &node, std::shared_ptr &walletInfo) findNewTransactions(node, walletInfo); } +void changePassword(std::shared_ptr &walletInfo, + std::vector args) +{ + std::string oldPassword, newPassword; + if (args.size() > 2) + { + std::cout << WarningMsg("Usage: change_password ") << std::endl; + return; + } + if (args.size() == 0) + { + if (walletInfo->walletPass != "") { + std::string tmpPassword = walletInfo->walletPass; + Tools::PasswordContainer pwdContainer(std::move(tmpPassword)); + if (!pwdContainer.read_and_validate("Enter old password: ")) + { + std::cout << WarningMsg("Incorrect password!") << std::endl; + return; + } + oldPassword = pwdContainer.password(); + } + } else { + if (args[0] != walletInfo->walletPass) { + std::cout << WarningMsg("Old password doesn't match!") << std::endl; + return; + } + oldPassword = args[0]; + } + if (args.size() < 2) + { + Tools::PasswordContainer pwdContainer; + if (!pwdContainer.read_password(true, "Enter new password: ")) + { + std::cout << WarningMsg("Aborted!") << std::endl; + return; + } + newPassword = pwdContainer.password(); + } else { + newPassword = args[1]; + } + try { + walletInfo->wallet.changePassword(oldPassword, newPassword); + walletInfo->wallet.save(); + walletInfo->walletPass = newPassword; + std::cout << InformationMsg("Password changed.") << std::endl; + } catch (std::exception&) { + std::cout << WarningMsg("Password change failed.") << std::endl; + } +} + void findNewTransactions(CryptoNote::INode &node, std::shared_ptr &walletInfo) { @@ -1470,7 +1537,7 @@ void findNewTransactions(CryptoNote::INode &node, { std::string warning = "Syncing may be stuck. Try restarting Bittoriumd.\n" - "If this persists, visit" + "If this persists, visit " "https://bitcointalk.org/index.php?topic=5028348" " for support."; std::cout << WarningMsg(warning) << std::endl; @@ -1584,3 +1651,53 @@ void viewWalletMsg() << "wallet so your balance can be correctly observed." << std::endl << std::endl; } + +//---------------------------------------------------------------------------------------------------- +bool processServerFeeAddressResponse(const std::string& response, std::string& fee_address) { + try { + std::stringstream stream(response); + Common::JsonValue json; + stream >> json; + + auto rootIt = json.getObject().find("fee_address"); + if (rootIt == json.getObject().end()) { + return false; + } + + fee_address = rootIt->second.getString(); + } + catch (std::exception&) { + return false; + } + + return true; +} + +//---------------------------------------------------------------------------------------------------- +std::string getFeeAddress(System::Dispatcher& dispatcher, std::string daemon_host, uint16_t daemon_port) { + + CryptoNote::HttpClient httpClient(dispatcher, daemon_host, daemon_port); + + CryptoNote::HttpRequest req; + CryptoNote::HttpResponse res; + + req.setUrl("/feeaddress"); + try { + httpClient.request(req, res); + } + catch (const std::exception& e) { + std::string errorMsg = e.what(); + std::cout << WarningMsg("Error connecting to the remote node: " + errorMsg) << std::endl; + } + + if (res.getStatus() != CryptoNote::HttpResponse::STATUS_200) { + std::cout << WarningMsg("Remote node returned code " + std::to_string(res.getStatus())) << std::endl; + } + + std::string address; + if (!processServerFeeAddressResponse(res.getBody(), address)) { + std::cout << WarningMsg("Failed to parse remote node response") << std::endl; + } + + return address; +} diff --git a/cryptonote/src/SimpleWallet/SimpleWallet.h b/cryptonote/src/SimpleWallet/SimpleWallet.h index db1b1c8..0076c4c 100644 --- a/cryptonote/src/SimpleWallet/SimpleWallet.h +++ b/cryptonote/src/SimpleWallet/SimpleWallet.h @@ -2,6 +2,7 @@ Copyright (C) 2018, The TurtleCoin developers Copyright (C) 2018, The PinkstarcoinV2 developers Copyright (C) 2018, The Bittorium developers +Copyright (C) 2018, The Karbo developers This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -89,6 +90,9 @@ void findNewTransactions(CryptoNote::INode &node, void reset(CryptoNote::INode &node, std::shared_ptr &walletInfo); +void changePassword(std::shared_ptr &walletInfo, + std::vector args); + void printOutgoingTransfer(CryptoNote::WalletTransaction t, CryptoNote::INode &node); @@ -144,3 +148,5 @@ ColouredMsg getPrompt(std::shared_ptr &walletInfo); CryptoNote::BlockDetails getBlock(uint32_t blockHeight, CryptoNote::INode &node); + +std::string getFeeAddress(System::Dispatcher& dispatcher, std::string daemon_host, uint16_t daemon_port); diff --git a/cryptonote/src/SimpleWallet/Tools.cpp b/cryptonote/src/SimpleWallet/Tools.cpp index 90404c9..4c71fe7 100644 --- a/cryptonote/src/SimpleWallet/Tools.cpp +++ b/cryptonote/src/SimpleWallet/Tools.cpp @@ -26,7 +26,7 @@ void confirmPassword(std::string walletPass) std::string tmpString = walletPass; Tools::PasswordContainer pwdContainer(std::move(tmpString)); - while (!pwdContainer.read_and_validate()) + while (!pwdContainer.read_and_validate("Enter password: ")) { std::cout << "Incorrect password! Try again." << std::endl; } diff --git a/cryptonote/src/SimpleWallet/Transfer.cpp b/cryptonote/src/SimpleWallet/Transfer.cpp index ff8a3c9..7c1c9f4 100644 --- a/cryptonote/src/SimpleWallet/Transfer.cpp +++ b/cryptonote/src/SimpleWallet/Transfer.cpp @@ -2,6 +2,7 @@ Copyright (C) 2018, The TurtleCoin developers Copyright (C) 2018, The PinkstarcoinV2 developers Copyright (C) 2018, The Bittorium developers +Copyright (C) 2018, The Karbo developers This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +20,9 @@ along with this program. If not, see . #include +// Forward declaration +extern std::string remote_fee_address; + bool parseAmount(std::string strAmount, uint64_t &amount) { boost::algorithm::trim(strAmount); @@ -227,7 +231,7 @@ void splitTx(CryptoNote::WalletGreen &wallet, = int(numTxMultiplier * (std::ceil(double(txSize) / double(maxSize)))); - /* Split the requested fee over each transaction, i.e. if a fee of 200 + /* Split the requested fee over each transaction, i.e. if a fee of 20 BTOR was requested and we split it into 4 transactions each one will have a fee of 5 BTOR. If the fee per transaction is less than the min fee, use the min fee. */ @@ -237,12 +241,10 @@ void splitTx(CryptoNote::WalletGreen &wallet, uint64_t totalCost = p.destinations[0].amount + totalFee; - /* If we have to use the minimum fee instead of splitting the total fee, - then it is possible the user no longer has the balance to cover this - transaction. So, we slightly lower the amount they are sending. */ if (totalCost > wallet.getActualBalance()) { - p.destinations[0].amount = wallet.getActualBalance() - totalFee; + std::cout << WarningMsg("Not enough balance to cover network fees.") << std::endl; + return; } uint64_t amountPerTx = p.destinations[0].amount / numTransactions; @@ -792,13 +794,19 @@ void doTransfer(uint16_t mixin, std::string address, uint64_t amount, std::shared_ptr walletInfo) { uint64_t balance = walletInfo->wallet.getActualBalance(); + uint64_t remote_node_fee = 0; + if (!remote_fee_address.empty()) + { + // Remote node fee is between 0.01 and 1.00 BTOR depending on transfer amount + remote_node_fee = std::min(UINT64_C(1), std::max(static_cast(amount * 0.000025), UINT64_C(100))); + } - if (balance < amount + fee) + if (balance < amount + fee + remote_node_fee) { std::cout << WarningMsg("You don't have enough funds to cover this " "transaction!") << std::endl << InformationMsg("Funds needed: " - + formatAmount(amount + fee)) + + formatAmount(amount + fee + remote_node_fee)) << std::endl << SuccessMsg("Funds available: " + formatAmount(balance)) << std::endl; @@ -815,6 +823,13 @@ void doTransfer(uint16_t mixin, std::string address, uint64_t amount, w.amount = amount; transfers.push_back(w); + if (!remote_fee_address.empty()) + { + w.address = remote_fee_address; + w.amount = remote_node_fee; + transfers.push_back(w); + } + CryptoNote::TransactionParameters p; p.destinations = transfers; p.fee = fee; @@ -1046,7 +1061,9 @@ Maybe getMixin() << std::endl << "Mixin is how many times your transaction is mixed " << "with others for privacy." << std::endl - << "Hit enter for the default mixin of 5: "; + << "Hit enter for the default mixin of " + << std::to_string(CryptoNote::parameters::DEFAULT_MIXIN) + << ": "; std::getline(std::cin, stringMixin); diff --git a/cryptonote/src/Transfers/BlockchainSynchronizer.cpp b/cryptonote/src/Transfers/BlockchainSynchronizer.cpp index da84c91..223b9e1 100644 --- a/cryptonote/src/Transfers/BlockchainSynchronizer.cpp +++ b/cryptonote/src/Transfers/BlockchainSynchronizer.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -247,11 +248,11 @@ bool BlockchainSynchronizer::setFutureStateIf(State s, std::function void BlockchainSynchronizer::actualizeFutureState() { std::unique_lock lk(m_stateMutex); - if (m_currentState == State::stopped && (m_futureState == State::deleteOldTxs || m_futureState == State::blockchainSync)) { // start(), immideately attach observer + if (m_currentState == State::stopped && (m_futureState == State::deleteOldTxs || m_futureState == State::blockchainSync)) { // start(), immediately attach observer m_node.addObserver(this); } - if (m_futureState == State::stopped && m_currentState != State::stopped) { // stop(), immideately detach observer + if (m_futureState == State::stopped && m_currentState != State::stopped) { // stop(), immediately detach observer m_node.removeObserver(this); } diff --git a/cryptonote/src/Wallet/WalletGreen.cpp b/cryptonote/src/Wallet/WalletGreen.cpp index af12293..e60f20c 100644 --- a/cryptonote/src/Wallet/WalletGreen.cpp +++ b/cryptonote/src/Wallet/WalletGreen.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2018-2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -1020,7 +1021,7 @@ std::vector WalletGreen::createAddressList(const std::vector::max() - m_currency.blockFutureTimeLimit()); + assert(creationTimestamp <= std::numeric_limits::max() - m_currency.blockFutureTimeLimit(-1)); std::vector addressDataList; addressDataList.push_back(NewAddressData{ spendPublicKey, spendSecretKey, creationTimestamp }); @@ -1053,7 +1054,7 @@ std::vector WalletGreen::doCreateAddressList(const std::vector::max() - m_currency.blockFutureTimeLimit()); + assert(addressData.creationTimestamp <= std::numeric_limits::max() - m_currency.blockFutureTimeLimit(-1)); std::string address = addWallet(addressData.spendPublicKey, addressData.spendSecretKey, addressData.creationTimestamp); m_logger(INFO, BRIGHT_WHITE) << "New wallet added " << address << ", creation timestamp " << addressData.creationTimestamp; addresses.push_back(std::move(address)); @@ -1064,7 +1065,7 @@ std::vector WalletGreen::doCreateAddressList(const std::vector(time(nullptr)); - if (minCreationTimestamp + m_currency.blockFutureTimeLimit() < currentTime) { + if (minCreationTimestamp + m_currency.blockFutureTimeLimit(-1) < currentTime) { m_logger(DEBUGGING) << "Reset is required"; save(WalletSaveLevel::SAVE_KEYS_AND_TRANSACTIONS, m_extra); shutdown(); diff --git a/cryptonote/src/version.h.in b/cryptonote/src/version.h.in index 6c3e4ba..c315a7c 100644 --- a/cryptonote/src/version.h.in +++ b/cryptonote/src/version.h.in @@ -2,12 +2,12 @@ #define STR(x) STR_HELPER(x) #define PROJECT_NAME "Bittorium" -#define PROJECT_SITE "https://bitcointalk.org/" -#define PROJECT_COPYRIGHT "Copyright 2018, The Bittorium Developers" +#define PROJECT_SITE "https://bittorium.org/" +#define PROJECT_COPYRIGHT "Copyright 2018-2019, The Bittorium Developers" #define APP_VER_MAJOR 0 #define APP_VER_MINOR 4 -#define APP_VER_REV 4 -#define APP_VER_BUILD 1258 +#define APP_VER_REV 5 +#define APP_VER_BUILD 1295 #define BUILD_COMMIT_ID "@VERSION@" #define PROJECT_VERSION STR(APP_VER_MAJOR) "." STR(APP_VER_MINOR) "." STR(APP_VER_REV) diff --git a/cryptonote/tests/CoreTests/BlockValidation.cpp b/cryptonote/tests/CoreTests/BlockValidation.cpp index 459cfd9..7a56f07 100644 --- a/cryptonote/tests/CoreTests/BlockValidation.cpp +++ b/cryptonote/tests/CoreTests/BlockValidation.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -38,7 +39,8 @@ bool lift_up_difficulty(const CryptoNote::Currency& currency, std::vector& ev BlockTemplate blk_1; generator.constructBlockManually(blk_1, blk_0, miner_account, test_generator::bf_major_ver | test_generator::bf_timestamp, m_blockMajorVersion, 0, - time(NULL) + 60 * 60 + m_currency->blockFutureTimeLimit()); + time(NULL) + 60 * 60 + m_currency->blockFutureTimeLimit(-1)); events.push_back(blk_1); DO_CALLBACK(events, "check_block_purged"); @@ -214,7 +216,7 @@ bool gen_block_ts_in_future_accepted::generate(std::vector& ev BlockTemplate blk_1; generator.constructBlockManually(blk_1, blk_0, miner_account, test_generator::bf_major_ver | test_generator::bf_timestamp, m_blockMajorVersion, 0, - time(NULL) - 60 + m_currency->blockFutureTimeLimit()); + time(NULL) - 60 + m_currency->blockFutureTimeLimit(-1)); events.push_back(blk_1); DO_CALLBACK(events, "check_block_accepted"); @@ -257,9 +259,10 @@ bool gen_block_invalid_nonce::generate(std::vector& events) co } // Create invalid nonce - Difficulty diffic = m_currency->nextDifficulty(timestamps, commulative_difficulties); - assert(1 < diffic); const BlockTemplate& blk_last = boost::get(events.back()); + int height = CachedBlock(blk_last).getBlockIndex() + 1; + Difficulty diffic = m_currency->nextDifficulty(m_blockMajorVersion, height, timestamps, commulative_difficulties); + assert(1 < diffic); uint64_t timestamp = blk_last.timestamp; BlockTemplate blk_3; do { @@ -655,6 +658,7 @@ gen_block_invalid_binary_format::gen_block_invalid_binary_format(uint8_t blockMa : m_corrupt_blocks_begin_idx(0), m_blockMajorVersion(blockMajorVersion) { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? IUpgradeDetector::UNDEF_HEIGHT : UINT32_C(0)); + currencyBuilder.upgradeHeightV3(CryptoNote::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER); m_currency.reset(new Currency(currencyBuilder.currency())); REGISTER_CALLBACK("check_all_blocks_purged", gen_block_invalid_binary_format::check_all_blocks_purged); @@ -684,7 +688,8 @@ bool gen_block_invalid_binary_format::generate(std::vector& ev Difficulty diffic; do { blk_last = boost::get(events.back()); - diffic = m_currency->nextDifficulty(timestamps, cummulative_difficulties); + int height = CachedBlock(blk_last).getBlockIndex() + 1; + diffic = m_currency->nextDifficulty(m_blockMajorVersion, height, timestamps, cummulative_difficulties); if (!lift_up_difficulty(*m_currency, events, timestamps, cummulative_difficulties, generator, 1, blk_last, miner_account, m_blockMajorVersion)) { return false; @@ -700,7 +705,8 @@ bool gen_block_invalid_binary_format::generate(std::vector& ev std::vector tx_hashes; tx_hashes.push_back(getObjectHash(tx_0)); size_t txs_size = getObjectBinarySize(tx_0); - diffic = m_currency->nextDifficulty(timestamps, cummulative_difficulties); + int height = CachedBlock(blk_last).getBlockIndex() + 1; + diffic = m_currency->nextDifficulty(m_blockMajorVersion, height, timestamps, cummulative_difficulties); if (!generator.constructBlockManually( blk_test, blk_last, miner_account, test_generator::bf_major_ver | test_generator::bf_diffic | test_generator::bf_timestamp | test_generator::bf_tx_hashes, diff --git a/cryptonote/tests/CoreTests/BlockValidation.h b/cryptonote/tests/CoreTests/BlockValidation.h index 9d5389e..0e8a3cd 100644 --- a/cryptonote/tests/CoreTests/BlockValidation.h +++ b/cryptonote/tests/CoreTests/BlockValidation.h @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -28,6 +29,8 @@ class CheckBlockPurged : public test_chain_unit_base { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? CryptoNote::IUpgradeDetector::UNDEF_HEIGHT : UINT32_C(0)); + currencyBuilder.upgradeHeightV3(CryptoNote::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER); + currencyBuilder.upgradeHeightV4(CryptoNote::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER); m_currency.reset(new Currency(currencyBuilder.currency())); REGISTER_CALLBACK("check_block_purged", CheckBlockPurged::check_block_purged); @@ -72,6 +75,8 @@ struct CheckBlockAccepted : public test_chain_unit_base { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? CryptoNote::IUpgradeDetector::UNDEF_HEIGHT : UINT32_C(0)); + currencyBuilder.upgradeHeightV3(CryptoNote::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER); + currencyBuilder.upgradeHeightV4(CryptoNote::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER); m_currency.reset(new Currency(currencyBuilder.currency())); REGISTER_CALLBACK("check_block_accepted", CheckBlockAccepted::check_block_accepted); @@ -306,6 +311,7 @@ struct gen_block_is_too_big : public CheckBlockPurged : CheckBlockPurged(1, blockMajorVersion) { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? CryptoNote::IUpgradeDetector::UNDEF_HEIGHT : UINT32_C(0)); + currencyBuilder.upgradeHeightV3(CryptoNote::parameters::CRYPTONOTE_MAX_BLOCK_NUMBER); currencyBuilder.maxBlockSizeInitial(std::numeric_limits::max() / 2); m_currency.reset(new Currency(currencyBuilder.currency())); } diff --git a/cryptonote/tests/Difficulty/Difficulty.cpp b/cryptonote/tests/Difficulty/Difficulty.cpp index 5df7a2b..308534c 100644 --- a/cryptonote/tests/Difficulty/Difficulty.cpp +++ b/cryptonote/tests/Difficulty/Difficulty.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2019, The Bittorium developers // // This file is part of Bytecoin. // @@ -56,7 +57,7 @@ int main(int argc, char *argv[]) { end = n - currency.difficultyLag(); begin = end - currency.difficultyWindow(); } - uint64_t res = currency.nextDifficulty( + uint64_t res = currency.nextDifficulty(1, n, vector(timestamps.begin() + begin, timestamps.begin() + end), vector(cumulative_difficulties.begin() + begin, cumulative_difficulties.begin() + end)); if (res != difficulty) { diff --git a/cryptonote/tests/UnitTests/INodeStubs.h b/cryptonote/tests/UnitTests/INodeStubs.h index 1d1a006..0d699de 100644 --- a/cryptonote/tests/UnitTests/INodeStubs.h +++ b/cryptonote/tests/UnitTests/INodeStubs.h @@ -44,6 +44,8 @@ class INodeDummyStub : public CryptoNote::INode virtual uint32_t getKnownBlockCount() const override { return 0; }; virtual uint64_t getLastLocalBlockTimestamp() const override { return 0; } virtual CryptoNote::BlockHeaderInfo getLastLocalBlockHeaderInfo() const override { return CryptoNote::BlockHeaderInfo(); } + virtual std::string getLastFeeAddress() const override { return ""; } + virtual std::string getLastCollateralHash() const override { return ""; } virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& height, const Callback& callback) override { callback(std::error_code()); }; @@ -71,6 +73,14 @@ class INodeDummyStub : public CryptoNote::INode callback(std::error_code()); } + virtual void getFeeAddress(std::string& feeAddress, const Callback& callback) { + callback(std::error_code()); + } + + virtual void getCollateralHash(std::string& collateralHash, const Callback& callback) { + callback(std::error_code()); + } + void updateObservers(); Tools::ObserverManager observerManager; diff --git a/src/CryptoNoteWrapper/InProcessNodeWorker.cpp b/src/CryptoNoteWrapper/InProcessNodeWorker.cpp index 178f98c..35b88ab 100644 --- a/src/CryptoNoteWrapper/InProcessNodeWorker.cpp +++ b/src/CryptoNoteWrapper/InProcessNodeWorker.cpp @@ -316,7 +316,7 @@ INodeAdapter::InitStatus InProcessNodeWorker::initCore() { if (!CryptoNote::DatabaseBlockchainCache::checkDBSchemeVersion(*m_database, m_loggerManager)) { m_database->shutdown(); - m_database->destoy(dbConfig); + m_database->destroy(dbConfig); m_database->init(dbConfig); } } catch (const std::system_error& _error) { diff --git a/src/Settings/Settings.cpp b/src/Settings/Settings.cpp index a6d96eb..281833c 100644 --- a/src/Settings/Settings.cpp +++ b/src/Settings/Settings.cpp @@ -73,7 +73,7 @@ const quint64 DEFAULT_OPTIMIZATION_MIXIN = 6; const quint64 VERSION_MAJOR = 2; const quint64 VERSION_MINOR = 0; -const quint64 VERSION_PATCH = 2; +const quint64 VERSION_PATCH = 4; }