diff --git a/README.md b/README.md index e4056c5c..d6e36ee4 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ To go futher you have to have a number of packages and utilities. You need at le * Boost (1.62 or newer): You need boost in `bcndev` folder. We do not configure to use boost installed by `apt-get`, because it is sometimes updated without your control by installing some unrelated packages. Also some users reported crashes after `find_package` finds headers from one version of boost and libraries from different version, or if installed boost uses dynamic linking. ``` - $bitsum> wget -c 'https://dl.bintray.com/boostorg/release/1.67.0/source/boost_1_67_0.tar.gz' - $bitsum> tar xf boost_1_67_0.tar.gz - $bitsum> mv boost_1_67_0 boost + $bitsum> wget -c 'https://dl.bintray.com/boostorg/release/1.65.1/source/boost_1_65_1.tar.gz' + $bitsum> tar xf boost_1_65_1.tar.gz + $bitsum> mv boost_1_65_1 boost $bitsum> cd boost $bitsum/boost> ./bootstrap.sh $bitsum/boost> ./b2 link=static cxxflags="-fPIC" linkflags="-pie" -j 8 --build-dir=build64 --stagedir=stage @@ -139,7 +139,7 @@ Then build and install Boost: ``` $~> cd ~/Downloads/boost_1_67_0/ $~/Downloads/boost_1_67_0> ./bootstrap.sh -$~/Downloads/boost_1_67_0> ./b2 -a -j 4 cxxflags="-stdlib=libc++ -std=c++14 -mmacosx-version-min=10.11 -isysroot/Users/user/Downloads/MacOSX10.11.sdk" install` +$~/Downloads/boost_1_67_0> ./b2 -a -j 4 cxxflags="-stdlib=libc++ -std=c++14 -mmacosx-version-min=10.11 -isysroot/Users/user/Downloads/MacOSX10.11.sdk -fPIC" linkflags="-pie" install` ``` Install OpenSSL to `bitsum/openssl` folder: diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 40bc3131..7cc2826d 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,5 +1,10 @@ ## Release Notes +### v1.18.6.22 +- Change POW algo (CryptoNight Lite, Variation 1) +- Change Difficulty algo (LWMA-2) +- Improvements for CXX 7 + ### v1.18.6.1 - Merge code with bytecoin v3.1.1 - Fix importing keys diff --git a/src/Core/BlockChainState.cpp b/src/Core/BlockChainState.cpp index 48d7f014..5ad4dd0c 100644 --- a/src/Core/BlockChainState.cpp +++ b/src/Core/BlockChainState.cpp @@ -256,7 +256,7 @@ std::string BlockChainState::check_standalone_consensus( return "PARENT_BLOCK_SIZE_TOO_BIG"; } const uint64_t now = time(nullptr); // It would be better to pass now through Node - if (block.header.timestamp > now + m_currency.block_future_time_limit) + if (block.header.timestamp > now + m_currency.get_block_future_time_limit(get_tip_height() + 1)) return "TIMESTAMP_TOO_FAR_IN_FUTURE"; if (block.header.timestamp < info->timestamp_median) return "TIMESTAMP_TOO_FAR_IN_PAST"; @@ -291,7 +291,7 @@ std::string BlockChainState::check_standalone_consensus( { std::vector timestamps; std::vector difficulties; - Height blocks_count = std::min(prev_info.height, m_currency.difficulty_blocks_count()); + Height blocks_count = std::min(prev_info.height, m_currency.get_difficulty_blocks_count(get_tip_height() + 1)); auto timestamps_window = get_tip_segment(prev_info, blocks_count, false); size_t actual_count = timestamps_window.size(); timestamps.resize(actual_count); @@ -367,10 +367,10 @@ void BlockChainState::calculate_consensus_values(const api::BlockHeader &prev_in last_blocks_sizes.push_back(it->block_size); *next_median_size = common::median_value(&last_blocks_sizes); - window = get_tip_segment(prev_info, m_currency.timestamp_check_window, false); - if (window.size() >= m_currency.timestamp_check_window) { + window = get_tip_segment(prev_info, m_currency.get_timestamp_check_window(get_tip_height() + 1), false); + if (window.size() >= m_currency.get_timestamp_check_window(get_tip_height() + 1)) { std::vector timestamps; - timestamps.reserve(m_currency.timestamp_check_window); + timestamps.reserve(m_currency.get_timestamp_check_window(get_tip_height() + 1)); for (auto it = window.begin(); it != window.end(); ++it) timestamps.push_back(it->timestamp); *next_median_timestamp = common::median_value(×tamps); // sorts timestamps @@ -378,10 +378,10 @@ void BlockChainState::calculate_consensus_values(const api::BlockHeader &prev_in // unlike median_value, here we select lesser of 2 middle values for // even-sized array, so // that m_next_unlock_timestamp will never decrease with block number - if (*next_unlock_timestamp < m_currency.block_future_time_limit) + if (*next_unlock_timestamp < m_currency.get_block_future_time_limit(get_tip_height() + 1)) *next_unlock_timestamp = 0; else - *next_unlock_timestamp -= m_currency.block_future_time_limit; + *next_unlock_timestamp -= m_currency.get_block_future_time_limit(get_tip_height() + 1); } else { *next_median_timestamp = 0; *next_unlock_timestamp = 0; @@ -400,7 +400,7 @@ bool BlockChainState::create_mining_block_template(BlockTemplate *b, const Accou { std::vector timestamps; std::vector difficulties; - Height blocks_count = std::min(get_tip_height(), m_currency.difficulty_blocks_count()); + Height blocks_count = std::min(get_tip_height(), m_currency.get_difficulty_blocks_count(get_tip_height() + 1)); timestamps.reserve(blocks_count); difficulties.reserve(blocks_count); auto timestamps_window = get_tip_segment(read_header(get_tip_bid()), blocks_count, false); diff --git a/src/Core/Config.cpp b/src/Core/Config.cpp index 14b20c2b..59b61ac5 100644 --- a/src/Core/Config.cpp +++ b/src/Core/Config.cpp @@ -19,7 +19,7 @@ static void parse_peer_and_add_to_container(const std::string &str, std::vector< using namespace common; using namespace bytecoin; -const static UUID BYTECOIN_NETWORK = { { 0x4C, 0x7E, 0x03, 0x32, 0x6A, 0x3F, 0x75, 0x16, 0x0B, 0x4C, 0xA1, 0xE3, 0x61, 0xD1, 0xDD, 0x17 } }; // Bender's nightmare +const static UUID BYTECOIN_NETWORK = { { 0x4C, 0x7E, 0x03, 0x32, 0x6A, 0x3F, 0x75, 0x16, 0x0B, 0x4C, 0xA1, 0xE3, 0x61, 0xD1, 0xDD, 0x20 } }; // Bender's nightmare Config::Config(common::CommandLine &cmd) : is_testnet(cmd.get_bool("--testnet")) diff --git a/src/Core/Currency.cpp b/src/Core/Currency.cpp index 23863a67..e3e3ae45 100644 --- a/src/Core/Currency.cpp +++ b/src/Core/Currency.cpp @@ -75,7 +75,15 @@ Currency::Currency(bool is_testnet) , locked_tx_allowed_delta_blocks(parameters::CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS) , upgrade_height_v2(parameters::UPGRADE_HEIGHT_V2) , upgrade_height_v3(parameters::UPGRADE_HEIGHT_V3) - , current_transaction_version(CURRENT_TRANSACTION_VERSION) { + , upgrade_height_v4(parameters::UPGRADE_HEIGHT_V4) + , current_transaction_version(CURRENT_TRANSACTION_VERSION) + , hardfork_v1_height(parameters::HARDFORK_V1_HEIGHT) + , hardfork_v2_height(parameters::HARDFORK_V2_HEIGHT) + , hardfork_v3_height(parameters::HARDFORK_V3_HEIGHT) + , timestamp_check_window_v2(parameters::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2) + , block_future_time_limit_v2(parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2) + , difficulty_window_v2(parameters::DIFFICULTY_WINDOW_V2) + , difficulty_blocks_count_v2(parameters::DIFFICULTY_BLOCKS_COUNT_V2) { if (is_testnet) { upgrade_height_v2 = 0; upgrade_height_v3 = static_cast(-1); @@ -142,7 +150,9 @@ uint8_t Currency::get_block_major_version_for_height(Height height) const { return 1; if (height > upgrade_height_v2 && height <= upgrade_height_v3) return 2; - return 3; // info.height > currency.upgrade_height_v3 + if (height > upgrade_height_v3 && height <= upgrade_height_v4) + return 3; + return 4; } uint32_t Currency::block_granted_full_reward_zone_by_block_version(uint8_t block_major_version) const { @@ -386,6 +396,16 @@ bool Currency::parse_amount(size_t number_of_decimal_places, const std::string & Difficulty Currency::next_difficulty(Height block_index, std::vector timestamps, std::vector cumulative_difficulties) const { + if (block_index <= hardfork_v2_height) + { + return next_difficulty_v1(block_index, timestamps, cumulative_difficulties); + } + + return next_difficulty_v2(timestamps, cumulative_difficulties); +} + +Difficulty Currency::next_difficulty_v1(Height block_index, std::vector timestamps, std::vector cumulative_difficulties) const +{ std::vector timestamps_o(timestamps); std::vector cumulativeDifficulties_o(cumulative_difficulties); size_t c_difficultyWindow = difficulty_window; @@ -431,8 +451,7 @@ Difficulty Currency::next_difficulty(Height block_index, return 0; } - //auto c = (low + timeSpan - 1) / timeSpan; - if (block_index >= 106195) { + if (block_index >= hardfork_v1_height) { if (high != 0) { return 0; } @@ -490,6 +509,44 @@ Difficulty Currency::next_difficulty(Height block_index, return (low + timeSpan - 1) / timeSpan; } +// LWMA-2 difficulty algorithm +// Copyright (c) 2017-2018 Zawy, MIT License +// https://github.com/zawy12/difficulty-algorithms/issues/3 +Difficulty Currency::next_difficulty_v2(std::vector timestamps, std::vector cumulative_difficulties) const +{ + int64_t T = difficulty_target; + int64_t N = difficulty_window_v2; + int64_t FTL = block_future_time_limit_v2; + int64_t L(0), ST, sum_3_ST(0), next_D, prev_D; + + if (timestamps.size() <= static_cast(N)) + { + return 1000; + } + + 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 = (cumulative_difficulties[N] - cumulative_difficulties[0]) * T * (N + 1) * 99 / (100 * 2 * L); + prev_D = cumulative_difficulties[N] - cumulative_difficulties[N - 1]; + + if (sum_3_ST < (8 * T) / 10) + { + next_D = (prev_D * 110) / 100; + } + + return static_cast(next_D); +} + bool Currency::check_proof_of_work_v1(const Hash &long_block_hash, const BlockTemplate &block, Difficulty current_difficulty) const { @@ -536,6 +593,7 @@ bool Currency::check_proof_of_work(const Hash &long_block_hash, return check_proof_of_work_v1(long_block_hash, block, current_difficulty); case 2: case 3: + case 4: return check_proof_of_work_v2(long_block_hash, block, current_difficulty); } // logger(ERROR, BrightRed) << "Unknown block major version: " << @@ -610,10 +668,36 @@ Hash bytecoin::get_block_long_hash(const BlockTemplate &bh, crypto::CryptoNightC auto raw_hashing_block = get_block_hashing_binary_array(bh); return crypto_ctx.cn_slow_hash(raw_hashing_block.data(), raw_hashing_block.size()); } - if (bh.major_version >= 2) { + if (bh.major_version >= 2 && bh.major_version < 4) { auto serializer = make_parent_block_serializer(bh, true, true); BinaryArray raw_hashing_block = seria::to_binary(serializer); return crypto_ctx.cn_slow_hash(raw_hashing_block.data(), raw_hashing_block.size()); } + if (bh.major_version >= 4) { + auto serializer = make_parent_block_serializer(bh, true, true); + BinaryArray raw_hashing_block = seria::to_binary(serializer); + return crypto_ctx.cn_lite_slow_hash_v1(raw_hashing_block.data(), raw_hashing_block.size()); + } + throw std::runtime_error("Unknown block major version."); } + +Height Currency::get_timestamp_check_window(Height height) const +{ + return height >= hardfork_v2_height ? timestamp_check_window_v2 : timestamp_check_window; +} + +Timestamp Currency::get_block_future_time_limit(Height height) const +{ + return height >= hardfork_v2_height ? block_future_time_limit_v2 : block_future_time_limit; +} + +Height bytecoin::Currency::get_difficulty_blocks_count(Height height) const +{ + if (height <= hardfork_v2_height) + { + return difficulty_blocks_count(); + } + + return difficulty_blocks_count_v2; +} \ No newline at end of file diff --git a/src/Core/Currency.hpp b/src/Core/Currency.hpp index a1619e6d..3424504a 100644 --- a/src/Core/Currency.hpp +++ b/src/Core/Currency.hpp @@ -49,6 +49,7 @@ class Currency { // Consensus calcs depend on those parameters Height difficulty_lag; size_t difficulty_cut; Height difficulty_blocks_count() const { return difficulty_window + difficulty_lag; } + Height get_difficulty_blocks_count(Height height) const; uint64_t max_block_size_initial; uint64_t max_block_size_growth_speed_numerator; @@ -59,10 +60,20 @@ class Currency { // Consensus calcs depend on those parameters Height upgrade_height_v2; Height upgrade_height_v3; + Height upgrade_height_v4; uint8_t get_block_major_version_for_height(Height) const; uint8_t current_transaction_version; + Height hardfork_v1_height; + Height hardfork_v2_height; + Height hardfork_v3_height; + + Height timestamp_check_window_v2; + Timestamp block_future_time_limit_v2; + Height difficulty_window_v2; + Height difficulty_blocks_count_v2; + size_t checkpoint_count() const; bool is_in_checkpoint_zone(Height index) const; bool check_block_checkpoint(Height index, const crypto::Hash &h, bool &is_checkpoint) const; @@ -89,6 +100,10 @@ class Currency { // Consensus calcs depend on those parameters Difficulty next_difficulty(Height block_index, std::vector timestamps, std::vector cumulative_difficulties) const; + + Difficulty next_difficulty_v1(Height block_index, std::vector timestamps, std::vector cumulative_difficulties) const; + + Difficulty next_difficulty_v2(std::vector timestamps, std::vector cumulative_difficulties) const; bool check_proof_of_work_v1( const Hash &long_block_hash, const BlockTemplate &block, Difficulty current_difficulty) const; @@ -106,6 +121,8 @@ class Currency { // Consensus calcs depend on those parameters return block_time + locked_tx_allowed_delta_seconds >= unlock_time; } static bool is_dust(Amount am); + Height get_timestamp_check_window(Height height) const; + Timestamp get_block_future_time_limit(Height height) const; static uint64_t get_penalized_amount(uint64_t amount, size_t median_size, size_t current_block_size); static std::string get_account_address_as_str(uint64_t prefix, const AccountPublicAddress &adr); static bool parse_account_address_string(uint64_t *prefix, AccountPublicAddress *adr, const std::string &str); diff --git a/src/Core/Node.cpp b/src/Core/Node.cpp index 7908820e..e0903364 100644 --- a/src/Core/Node.cpp +++ b/src/Core/Node.cpp @@ -321,7 +321,7 @@ void Node::advance_long_poll() { if (!prevent_sleep && m_block_chain.get_tip().timestamp < now - 86400) prevent_sleep = std::make_unique("Downloading blockchain"); if (prevent_sleep && - m_block_chain.get_tip().timestamp > now - m_block_chain.get_currency().block_future_time_limit * 2) + m_block_chain.get_tip().timestamp > now - m_block_chain.get_currency().get_block_future_time_limit(m_block_chain.get_tip_height() + 1) * 2) prevent_sleep = nullptr; if (m_long_poll_http_clients.empty()) return; @@ -537,9 +537,9 @@ bool Node::on_wallet_sync3(http::Client *, http::RequestData &&, json_rpc::Reque if (req.max_count > api::bytecoind::SyncBlocks::Request::MAX_COUNT) throw std::runtime_error( "Too big max_count - must be < " + std::to_string(api::bytecoind::SyncBlocks::Request::MAX_COUNT)); - auto first_block_timestamp = req.first_block_timestamp < m_block_chain.get_currency().block_future_time_limit + auto first_block_timestamp = req.first_block_timestamp < m_block_chain.get_currency().get_block_future_time_limit(m_block_chain.get_tip_height() + 1) ? 0 - : req.first_block_timestamp - m_block_chain.get_currency().block_future_time_limit; + : req.first_block_timestamp - m_block_chain.get_currency().get_block_future_time_limit(m_block_chain.get_tip_height() + 1); Height full_offset = m_block_chain.get_timestamp_lower_bound_block_index(first_block_timestamp); Height start_block_index; std::vector supplement = diff --git a/src/Core/WalletState.cpp b/src/Core/WalletState.cpp index 2f909af8..3b20abd2 100644 --- a/src/Core/WalletState.cpp +++ b/src/Core/WalletState.cpp @@ -306,7 +306,7 @@ void WalletState::wallet_addresses_updated() { // case of ctrl-c } while (m_tip_height + 1 > m_tail_height && - get_tip().timestamp + m_currency.block_future_time_limit >= + get_tip().timestamp + m_currency.get_block_future_time_limit(get_tip_height() + 1) >= undo_timestamp) { // Undo excess blocks in case timestamps are out of // order undo_block(m_tip_height); @@ -335,7 +335,7 @@ std::vector WalletState::generate_new_addresses(const std::vector< return result; } while (m_tip_height + 1 > m_tail_height && - get_tip().timestamp + m_currency.block_future_time_limit >= + get_tip().timestamp + m_currency.get_block_future_time_limit(get_tip_height() + 1) >= undo_timestamp) { // Undo excess blocks in case timestamps are out of // order undo_block(m_tip_height); @@ -383,7 +383,7 @@ bool WalletState::sync_with_blockchain(api::bytecoind::SyncBlocks::Response &res const api::BlockHeader &header = resp.blocks.at(bin).header; if (m_tip_height + 1 != m_tail_height && header.previous_block_hash != m_tip.hash) return false; - if (header.timestamp + m_currency.block_future_time_limit >= m_wallet.get_oldest_timestamp()) { + if (header.timestamp + m_currency.get_block_future_time_limit(get_tip_height() + 1) >= m_wallet.get_oldest_timestamp()) { const auto &block_gi = resp.blocks.at(bin).global_indices; PreparedWalletBlock pb = preparator.get_ready_work(m_tip_height + 1); // PreparedWalletBlock pb(std::move(resp.blocks.at(bin).block), m_wallet.get_view_secret_key()); diff --git a/src/Core/WalletSync.cpp b/src/Core/WalletSync.cpp index 55232195..f31796be 100644 --- a/src/Core/WalletSync.cpp +++ b/src/Core/WalletSync.cpp @@ -78,7 +78,7 @@ void WalletSync::advance_sync() { if (!prevent_sleep && m_wallet_state.get_tip().timestamp < now - 86400) prevent_sleep = std::make_unique("Synchronizing wallet"); if (prevent_sleep && - m_wallet_state.get_tip().timestamp > now - m_wallet_state.get_currency().block_future_time_limit * 2) + m_wallet_state.get_tip().timestamp > now - m_wallet_state.get_currency().get_block_future_time_limit(m_wallet_state.get_tip_height() + 1) * 2) prevent_sleep = nullptr; if (m_sync_request) return; diff --git a/src/CryptoNoteConfig.hpp b/src/CryptoNoteConfig.hpp index 82c62654..0f6396de 100644 --- a/src/CryptoNoteConfig.hpp +++ b/src/CryptoNoteConfig.hpp @@ -13,6 +13,16 @@ namespace bytecoin { namespace parameters { +const uint32_t HARDFORK_V1_HEIGHT = 106195; +const uint32_t HARDFORK_V2_HEIGHT = 162000; +const uint32_t HARDFORK_V3_HEIGHT = 4294967294; + +const uint32_t DIFFICULTY_TARGET = 120; // seconds +const uint32_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 = DIFFICULTY_TARGET * 3; +const uint32_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 = 11; +const uint64_t DIFFICULTY_WINDOW_V2 = 60; +const uint64_t DIFFICULTY_BLOCKS_COUNT_V2 = DIFFICULTY_WINDOW_V2 + 1; + const uint32_t CRYPTONOTE_MAX_BLOCK_NUMBER = 500000000; const uint32_t CRYPTONOTE_MAX_BLOCK_BLOB_SIZE = 500000000; const uint32_t CRYPTONOTE_MAX_TX_SIZE = 1000000000; @@ -38,7 +48,6 @@ const size_t CRYPTONOTE_DISPLAY_DECIMAL_POINT = 10; const uint64_t MINIMUM_FEE = 1000000; // pow(10, 6) const uint64_t DEFAULT_DUST_THRESHOLD = 1000000; // pow(10, 6) -const uint32_t DIFFICULTY_TARGET = 120; // seconds constexpr uint32_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY(uint32_t difficulty_target) { return 24 * 60 * 60 / difficulty_target; } @@ -73,6 +82,7 @@ const uint32_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60 * 24; // seconds, one d const uint32_t UPGRADE_HEIGHT_V2 = 1; const uint32_t UPGRADE_HEIGHT_V3 = 2; +const uint32_t UPGRADE_HEIGHT_V4 = HARDFORK_V2_HEIGHT; const char CRYPTONOTE_BLOCKS_FILENAME[] = "blocks.bin"; const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexes.bin"; @@ -134,5 +144,7 @@ constexpr const CheckpointData CHECKPOINTS[] = { { 130000, "80add5a415bf8c325497923e039db00de2a086a9dda95e142b03f267e7b7d0c0" }, { 140000, "efab6c622247beaa832a9f14c0a4844055c442baa089c5586ff34cd23db69107" }, { 150000, "9e1582b1d8b2539947299655f1b12d9a65d379d1f5cae650e8049ff083c0b39a" }, + { 160000, "a1d285e1faffe828bc2a16ed94e9da284a9ee1960748fe88dc7261871ec14a1c" }, + { 162000, "645a8e5bf0f8a10ee5f950f7abf7113b1f7b0e5cc50261234fd5d79acf3b1164" }, }; } // CryptoNote diff --git a/src/bitsum.rc b/src/bitsum.rc index 5eb9dc56..4deb481f 100644 --- a/src/bitsum.rc +++ b/src/bitsum.rc @@ -5,8 +5,8 @@ // 1 VERSIONINFO - FILEVERSION 1,18,6,1 - PRODUCTVERSION 1,18,6,1 + FILEVERSION 1,18,6,22 + PRODUCTVERSION 1,18,6,22 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -19,12 +19,12 @@ BEGIN BEGIN VALUE "CompanyName", "Bitsum Foundation" VALUE "FileDescription", "Bitsum" - VALUE "FileVersion", "1.18.4.5" + VALUE "FileVersion", "1.18.6.22" VALUE "InternalName", "bitsum.rc" VALUE "LegalCopyright", "Copyright (C) Bitsum Foundation, 2018" VALUE "OriginalFilename", "bitsum.rc" VALUE "ProductName", "Bitsum" - VALUE "ProductVersion", "1.18.6.1" + VALUE "ProductVersion", "1.18.6.22" END END BLOCK "VarFileInfo" diff --git a/src/bitsum/Explorer.cpp b/src/bitsum/Explorer.cpp index 6854ef0b..c90a96ab 100644 --- a/src/bitsum/Explorer.cpp +++ b/src/bitsum/Explorer.cpp @@ -2,17 +2,17 @@ using namespace crypto; -namespace explorer { - +namespace explorer +{ Explorer::Explorer(bytecoin::BlockChainState* blockChain) { - _blockChain = blockChain; + _blockchain = blockChain; } crypto::Hash Explorer::GetBlockHash(uint32_t height) { crypto::Hash result; - _blockChain->read_chain(height, &result); + _blockchain->read_chain(height, &result); return result; } @@ -25,18 +25,81 @@ namespace explorer { RawBlock rb; api::BlockHeader bh; - _blockChain->read_block(bid, &rb); - _blockChain->read_header(bid, &bh); + _blockchain->read_block(bid, &rb); + _blockchain->read_header(bid, &bh); result.height = height; std::copy(std::begin(bid.data), std::end(bid.data), std::begin(result.hash)); result.timestamp = bh.timestamp; result.size = bh.block_size + ((uint32_t)rb.block.size() - (bh.block_size - bh.transactions_cumulative_size)); result.tx_count = (uint32_t)rb.transactions.capacity() + 1; + result.difficulty = bh.difficulty; return result; } + BlockPreview2 Explorer::GetBlockPreview2(uint32_t height) + { + crypto::Hash bid = GetBlockHash(height); + + BlockPreview2 result; + RawBlock rb; + Block b; + //api::BlockHeader bh; + + + _blockchain->read_block(bid, &rb); + b.from_raw_block(rb); + result.length = b.header.transaction_hashes.capacity(); + //result.hashes + + //result.hash = b.header.transaction_hashes[0]; + + //std::vector hh(b.header.transaction_hashes); + + //for each (crypto::Hash h in b.header.transaction_hashes) + //{ + // + //} + //_blockchain->read_header(bid, &bh); + + + + //result.height = height; + //std::copy(std::begin(bid.data), std::end(bid.data), std::begin(result.hash)); + //result.timestamp = bh.timestamp; + //result.size = bh.block_size + ((uint32_t)rb.block.size() - (bh.block_size - bh.transactions_cumulative_size)); + //result.tx_count = (uint32_t)rb.transactions.capacity() + 1; + //result.difficulty = bh.difficulty; + + return result; + } + + crypto::Hash Explorer::GetBlockPreview3(uint32_t height) + { + crypto::Hash bid = GetBlockHash(height); + + BlockPreview2 result; + RawBlock rb; + Block b; + + _blockchain->read_block(bid, &rb); + b.from_raw_block(rb); + return b.header.transaction_hashes[0]; + } + + std::vector Explorer::GetBlockPreview4(uint32_t height) + { + crypto::Hash bid = GetBlockHash(height); + + BlockPreview2 result; + RawBlock rb; + Block b; + + _blockchain->read_block(bid, &rb); + b.from_raw_block(rb); + return b.header.transaction_hashes; + } Explorer::~Explorer() { diff --git a/src/bitsum/Explorer.hpp b/src/bitsum/Explorer.hpp index 19ee1d84..1a817bf7 100644 --- a/src/bitsum/Explorer.hpp +++ b/src/bitsum/Explorer.hpp @@ -1,34 +1,48 @@ #pragma once #include -#include "crypto/types.hpp" -#include "CryptoNote.hpp" #include "Core/BlockChainState.hpp" +#include "CryptoNote.hpp" +#include "crypto/types.hpp" #include "rpc_api.hpp" -namespace explorer { - +namespace explorer +{ using namespace crypto; using namespace bytecoin; - typedef struct Hash { uint8_t bytes[32]; } Hash; + //typedef struct Hash + //{ + // uint8_t bytes[32]; + //}; - struct BlockPreview { + struct BlockPreview + { uint8_t hash[32]; uint32_t height; uint32_t timestamp; uint32_t size; uint32_t tx_count; + uint64_t difficulty; + }; + + struct BlockPreview2 + { + uint32_t length; + //crypto::Hash * hash; + std::vector hash; }; class Explorer { - bytecoin::BlockChainState* _blockChain; + bytecoin::BlockChainState *_blockchain; + public: - Explorer(bytecoin::BlockChainState* blockChain); + Explorer(bytecoin::BlockChainState *blockChain); crypto::Hash GetBlockHash(uint32_t height); BlockPreview GetBlockPreview(uint32_t height); + BlockPreview2 GetBlockPreview2(uint32_t height); + crypto::Hash GetBlockPreview3(uint32_t height); + std::vector GetBlockPreview4(uint32_t height); ~Explorer(); }; - } - diff --git a/src/bitsum/NodeWrapper.cpp b/src/bitsum/NodeWrapper.cpp index ef3363b1..c8a1512f 100644 --- a/src/bitsum/NodeWrapper.cpp +++ b/src/bitsum/NodeWrapper.cpp @@ -11,6 +11,7 @@ #include "common/Base58.hpp" #include "seria/BinaryInputStream.hpp" #include "seria/BinaryOutputStream.hpp" +#include "Explorer.hpp" using namespace bytecoin; using namespace common; @@ -20,16 +21,17 @@ namespace bitsum { boost::asio::io_service node_io; std::unique_ptr node_lock; std::unique_ptr blockchain_state; + std::unique_ptr explorer; - EXPORT int StartNode(bool coutRedirect = true) + EXPORT int StartNode(bool coutRedirect = false) { try { - if (coutRedirect) { - std::cout.rdbuf(nullptr); - } - else { + //if (coutRedirect) { + // std::cout.rdbuf(nullptr); + //} + //else { common::console::UnicodeConsoleSetup console_setup; - } + //} auto idea_start = std::chrono::high_resolution_clock::now(); @@ -56,6 +58,8 @@ namespace bitsum { auto idea_ms = std::chrono::duration_cast( std::chrono::high_resolution_clock::now() - idea_start); std::cout << "bitsumd started seconds=" << double(idea_ms.count()) / 1000 << std::endl; + explorer = std::make_unique(blockchain_state.get()); + while (!node_io.stopped()) { if (node.on_idle()) // Using it to load blockchain node_io.poll(); @@ -81,4 +85,32 @@ namespace bitsum { return -1; } } + + EXPORT void GetBlockPreview(uint32_t height, explorer::BlockPreview &blockPreview) + { + blockPreview = explorer::BlockPreview(); + blockPreview = explorer->GetBlockPreview(height); + } + + EXPORT void GetBlockPreview2(uint32_t height, explorer::BlockPreview2 &blockPreview) + { + blockPreview = explorer::BlockPreview2(); + blockPreview = explorer->GetBlockPreview2(height); + } + + EXPORT crypto::Hash GetBlockPreview3(uint32_t height) + { + return explorer->GetBlockPreview3(height); + } + + EXPORT explorer::BlockPreview2 GetBlockPreview4() + { + //uint8_t data[32]; + auto d = explorer->GetBlockPreview4(15000); + explorer::BlockPreview2 result = explorer::BlockPreview2(); + result.length = d.capacity(); + result.hash = d; + + return result; + } } \ No newline at end of file diff --git a/src/common/Base58.cpp b/src/common/Base58.cpp index 4ce89357..3fdd5eed 100644 --- a/src/common/Base58.cpp +++ b/src/common/Base58.cpp @@ -69,33 +69,17 @@ uint64_t uint_8be_to_64(const uint8_t *data, size_t size) { assert(1 <= size && size <= sizeof(uint64_t)); uint64_t res = 0; - switch (9 - size) { - case 1: - res |= *data++; - case 2: - res <<= 8; - res |= *data++; - case 3: - res <<= 8; - res |= *data++; - case 4: - res <<= 8; - res |= *data++; - case 5: - res <<= 8; - res |= *data++; - case 6: - res <<= 8; - res |= *data++; - case 7: - res <<= 8; - res |= *data++; - case 8: - res <<= 8; - res |= *data; - break; - default: - assert(false); + switch (9 - size) + { + case 1: res |= *data++; /* fallthrough */ + case 2: res <<= 8; res |= *data++; /* fallthrough */ + case 3: res <<= 8; res |= *data++; /* fallthrough */ + case 4: res <<= 8; res |= *data++; /* fallthrough */ + case 5: res <<= 8; res |= *data++; /* fallthrough */ + case 6: res <<= 8; res |= *data++; /* fallthrough */ + case 7: res <<= 8; res |= *data++; /* fallthrough */ + case 8: res <<= 8; res |= *data; break; + default: assert(false); } return res; diff --git a/src/crypto/cryptonight-variants.h b/src/crypto/cryptonight-variants.h new file mode 100644 index 00000000..b44ed5f3 --- /dev/null +++ b/src/crypto/cryptonight-variants.h @@ -0,0 +1,53 @@ +// Copyright (c) 2018, The Monero Project +// Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers + +/* The following was adapted from the Monero Cryptonight variant change of April 2018. */ + +#include + +#pragma once + +static inline void xor64(uint64_t *a, const uint64_t b) +{ + *a ^= b; +} + +#define VARIANT1_1(p) \ + do if (variant > 0) \ + { \ + const uint8_t tmp = ((const uint8_t*)(p))[11]; \ + static const uint32_t table = 0x75310; \ + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ + ((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \ + } while(0); + +#define VARIANT1_2(p) \ + do if (variant > 0) \ + { \ + xor64(p, tweak1_2); \ + } while(0); + +#define VARIANT1_CHECK() \ + do if (length < 43) \ + { \ + fprintf(stderr, "Cryptonight variants need at least 43 bytes of data. Aborting."); \ + abort(); \ + } while(0); + +#define NONCE_POINTER (((const uint8_t*)data)+35) + +#define VARIANT1_PORTABLE_INIT() \ + uint8_t tweak1_2[8]; \ + do if (variant > 0) \ + { \ + VARIANT1_CHECK(); \ + memcpy(&tweak1_2, &state.hs.b[192], sizeof(tweak1_2)); \ + xor64(tweak1_2, NONCE_POINTER); \ + } while(0) + +#define VARIANT1_INIT64() \ + if (variant > 0) \ + { \ + VARIANT1_CHECK(); \ + } \ + const uint64_t tweak1_2 = variant > 0 ? (ctx->state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0 diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index c0e0e64e..6419f7d9 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -15,7 +15,8 @@ enum { void cn_fast_hash(const void *data, size_t length, unsigned char *hash); -void cn_slow_hash(void *, const void *, size_t, void *); +//void cn_slow_hash(void *, const void *, size_t, void *); +void cn_slow_hash(void *, const void *, size_t, void *, int, int); void tree_hash(const unsigned char (*hashes)[HASH_SIZE], size_t count, unsigned char *root_hash); size_t tree_depth(size_t count); diff --git a/src/crypto/hash.hpp b/src/crypto/hash.hpp index 2a40af84..32ae7faa 100644 --- a/src/crypto/hash.hpp +++ b/src/crypto/hash.hpp @@ -29,11 +29,20 @@ class CryptoNightContext { void operator=(const CryptoNightContext &) = delete; inline void cn_slow_hash(const void *src_data, size_t length, unsigned char *hash) { - crypto::cn_slow_hash(data, src_data, length, hash); + crypto::cn_slow_hash(data, src_data, length, hash, 0, 0); } inline Hash cn_slow_hash(const void *src_data, size_t length) { Hash hash; - crypto::cn_slow_hash(data, src_data, length, hash.data); + crypto::cn_slow_hash(data, src_data, length, hash.data, 0, 0); + return hash; + } + + inline void cn_lite_slow_hash_v1(const void *src_data, size_t length, unsigned char *hash) { + crypto::cn_slow_hash(data, src_data, length, hash, 1, 1); + } + inline Hash cn_lite_slow_hash_v1(const void *src_data, size_t length) { + Hash hash; + crypto::cn_slow_hash(data, src_data, length, hash.data, 1, 1); return hash; } diff --git a/src/crypto/slow-hash_x86.c b/src/crypto/slow-hash_x86.c index ff707089..642372f1 100644 --- a/src/crypto/slow-hash_x86.c +++ b/src/crypto/slow-hash_x86.c @@ -4,6 +4,7 @@ #include #include #include +#include "crypto/cryptonight-variants.h" #ifdef __APPLE__ #include "TargetConditionals.h" @@ -40,7 +41,14 @@ #endif #define MEMORY (1 << 21) /* 2 MiB */ -#define ITER (1 << 20) +#define ITER (1 << 19) +#define MASK 0x1FFFF0 + +// Cryptonight Lite +#define LITE_MEMORY (1 << 20) /* 1 MiB */ +#define LITE_ITER (1 << 18) +#define LITE_MASK 0xFFFF0 + #define AES_BLOCK_SIZE 16 #define AES_KEY_SIZE 32 /*16*/ #define INIT_SIZE_BLK 8 @@ -178,17 +186,17 @@ static int cpu_has_aesni(void){ return (ecx & (1 << 25)) ? 1 : 0; } -static void cn_slow_hash_runtime_aes_check(void * a, const void * b, size_t c, void * d){ +static void cn_slow_hash_runtime_aes_check(void * a, const void * b, size_t c, void * d, int lite, int variant){ if( cpu_has_aesni() ) - cn_slow_hash_aesni(a, b, c, d); + cn_slow_hash_aesni(a, b, c, d, lite, variant); else - cn_slow_hash_noaesni(a, b, c, d); + cn_slow_hash_noaesni(a, b, c, d, lite, variant); } -static void (*cn_slow_hash_fp)(void *, const void *, size_t, void *) = cn_slow_hash_runtime_aes_check; +static void (*cn_slow_hash_fp)(void *, const void *, size_t, void *, int lite, int variant) = cn_slow_hash_runtime_aes_check; -void cn_slow_hash(void * a, const void * b, size_t c, void * d){ - (*cn_slow_hash_fp)(a, b, c, d); +void cn_slow_hash(void * a, const void * b, size_t c, void * d, int lite, int variant){ + (*cn_slow_hash_fp)(a, b, c, d, lite, variant); } // If INITIALIZER fails to compile on your platform, just comment out 3 lines below diff --git a/src/crypto/slow-hash_x86.inl b/src/crypto/slow-hash_x86.inl index d5aee11a..1e59de4c 100644 --- a/src/crypto/slow-hash_x86.inl +++ b/src/crypto/slow-hash_x86.inl @@ -9,16 +9,21 @@ cn_slow_hash_aesni #else cn_slow_hash_noaesni #endif -(void *restrict context, const void *restrict data, size_t length, void *restrict hash) +(void *restrict context, const void *restrict data, size_t length, void *restrict hash, int lite, int variant) { #define ctx ((struct cn_ctx *) context) ALIGNED_DECL(uint8_t ExpandedKey[256], 16); size_t i; __m128i *longoutput, *expkey, *xmminput, b_x; ALIGNED_DECL(uint64_t a[2], 16); + size_t memory = lite ? LITE_MEMORY : MEMORY; + size_t iterations = lite ? LITE_ITER : ITER; + size_t mask = lite ? LITE_MASK : MASK; + hash_process(&ctx->state.hs, (const uint8_t*) data, length); memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); + VARIANT1_INIT64(); #if defined(AESNI) memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); ExpandAESKey256(ExpandedKey); @@ -32,10 +37,10 @@ cn_slow_hash_noaesni expkey = (__m128i *) ExpandedKey; xmminput = (__m128i *) ctx->text; - //for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) + //for (i = 0; likely(i < memory); i += INIT_SIZE_BYTE) // aesni_parallel_noxor(&ctx->long_state[i], ctx->text, ExpandedKey); - for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) + for (i = 0; likely(i < memory); i += INIT_SIZE_BYTE) { #if defined(AESNI) for(size_t j = 0; j < 10; j++) @@ -79,9 +84,9 @@ cn_slow_hash_noaesni a[0] = ctx->a[0]; a[1] = ctx->a[1]; - for(i = 0; likely(i < 0x80000); i++) + for(i = 0; likely(i < iterations); i++) { - __m128i c_x = _mm_load_si128((__m128i *)&ctx->long_state[a[0] & 0x1FFFF0]); + __m128i c_x = _mm_load_si128((__m128i *)&ctx->long_state[a[0] & mask]); __m128i a_x = _mm_load_si128((__m128i *)a); ALIGNED_DECL(uint64_t c[2], 16); ALIGNED_DECL(uint64_t b[2], 16); @@ -94,12 +99,13 @@ cn_slow_hash_noaesni #endif _mm_store_si128((__m128i *)c, c_x); - //__builtin_prefetch(&ctx->long_state[c[0] & 0x1FFFF0], 0, 1); + //__builtin_prefetch(&ctx->long_state[c[0] & mask], 0, 1); b_x = _mm_xor_si128(b_x, c_x); - _mm_store_si128((__m128i *)&ctx->long_state[a[0] & 0x1FFFF0], b_x); + _mm_store_si128((__m128i *)&ctx->long_state[a[0] & mask], b_x); + VARIANT1_1(&ctx->long_state[a[0] & mask]); - nextblock = (uint64_t *)&ctx->long_state[c[0] & 0x1FFFF0]; + nextblock = (uint64_t *)&ctx->long_state[c[0] & mask]; b[0] = nextblock[0]; b[1] = nextblock[1]; @@ -120,14 +126,15 @@ cn_slow_hash_noaesni a[0] += hi; a[1] += lo; } - dst = (uint64_t *) &ctx->long_state[c[0] & 0x1FFFF0]; + dst = (uint64_t *) &ctx->long_state[c[0] & mask]; dst[0] = a[0]; dst[1] = a[1]; a[0] ^= b[0]; a[1] ^= b[1]; + VARIANT1_2(dst + 1); b_x = c_x; - //__builtin_prefetch(&ctx->long_state[a[0] & 0x1FFFF0], 0, 3); + //__builtin_prefetch(&ctx->long_state[a[0] & mask], 0, 3); } memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); @@ -139,10 +146,10 @@ cn_slow_hash_noaesni memcpy(ExpandedKey, ctx->aes_ctx->key->exp_data, ctx->aes_ctx->key->exp_data_len); #endif - //for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) + //for (i = 0; likely(i < memory); i += INIT_SIZE_BYTE) // aesni_parallel_xor(&ctx->text, ExpandedKey, &ctx->long_state[i]); - for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) + for (i = 0; likely(i < memory); i += INIT_SIZE_BYTE) { xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]); xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]); diff --git a/src/main_bitsumd.cpp b/src/main_bitsumd.cpp index ac1914dc..e1d8f0f3 100644 --- a/src/main_bitsumd.cpp +++ b/src/main_bitsumd.cpp @@ -25,7 +25,6 @@ static const char USAGE[] = Options: --allow-local-ip Allow local ip add to peer list, mostly in debug purposes. - --p2p-bind-address= Interface and port for P2P network protocol [default: 0.0.0.0:28080]. --p2p-external-port= External port for P2P network protocol, if port forwarding used with NAT [default: 28080]. --daemon-rpc-bind-address= Interface and port for bitsumd RPC [default: 127.0.0.1:28081]. @@ -36,7 +35,7 @@ static const char USAGE[] = --backup-blockchain= Perform hot backup of blockchain into specified backup data folder, then exit. --data-folder= Folder for blockchain, logs and peer DB [default: )" platform_DEFAULT_DATA_FOLDER_PATH_PREFIX R"(bitsum]. - --bytecoind-authorization= HTTP authorization for RPC. + --rpc-authorization= HTTP authorization for RPC. )" #if platform_USE_SSL R"( --ssl-certificate-pem-file= Full path to file containing both server SSL certificate and private key in PEM format. diff --git a/src/version.hpp b/src/version.hpp index cb2d8434..a2d9cabb 100644 --- a/src/version.hpp +++ b/src/version.hpp @@ -4,8 +4,8 @@ #pragma once // defines are for Windows resource compiler -#define bytecoin_VERSION_WINDOWS_COMMA 1, 18, 6, 1 -#define bytecoin_VERSION_STRING "1.18.6.1" +#define bytecoin_VERSION_WINDOWS_COMMA 1, 18, 6, 22 +#define bytecoin_VERSION_STRING "1.18.6.22" #ifndef RC_INVOKED // Windows resource compiler