diff options
-rw-r--r-- | cmake/Version.cmake | 2 | ||||
-rw-r--r-- | src/cryptonote_basic/cryptonote_format_utils.cpp | 37 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 47 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 33 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 4 | ||||
-rw-r--r-- | tests/unit_tests/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/unit_tests/hardfork.cpp | 2 | ||||
-rw-r--r-- | tests/unit_tests/main.cpp | 11 |
8 files changed, 93 insertions, 45 deletions
diff --git a/cmake/Version.cmake b/cmake/Version.cmake index 439c4c5ae..3677e80d7 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -28,7 +28,7 @@ function (write_static_version_header hash) set(VERSIONTAG "${hash}") - configure_file("src/version.cpp.in" "version.cpp") + configure_file("${CMAKE_SOURCE_DIR}/src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp") endfunction () find_package(Git QUIET) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index ae7c1c0ae..3c6885896 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -124,6 +124,40 @@ namespace cryptonote return h; } //--------------------------------------------------------------- + bool expand_transaction_1(transaction &tx, bool base_only) + { + if (tx.version >= 2 && !is_coinbase(tx)) + { + rct::rctSig &rv = tx.rct_signatures; + if (rv.outPk.size() != tx.vout.size()) + { + LOG_PRINT_L1("Failed to parse transaction from blob, bad outPk size in tx " << get_transaction_hash(tx)); + return false; + } + for (size_t n = 0; n < tx.rct_signatures.outPk.size(); ++n) + rv.outPk[n].dest = rct::pk2rct(boost::get<txout_to_key>(tx.vout[n].target).key); + + if (!base_only) + { + const bool bulletproof = rv.type == rct::RCTTypeFullBulletproof || rv.type == rct::RCTTypeSimpleBulletproof; + if (bulletproof) + { + if (rv.p.bulletproofs.size() != tx.vout.size()) + { + LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx)); + return false; + } + for (size_t n = 0; n < rv.outPk.size(); ++n) + { + rv.p.bulletproofs[n].V.resize(1); + rv.p.bulletproofs[n].V[0] = rv.outPk[n].mask; + } + } + } + } + return true; + } + //--------------------------------------------------------------- bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx) { std::stringstream ss; @@ -131,6 +165,7 @@ namespace cryptonote binary_archive<false> ba(ss); bool r = ::serialization::serialize(ba, tx); CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); tx.invalidate_hashes(); return true; } @@ -142,6 +177,7 @@ namespace cryptonote binary_archive<false> ba(ss); bool r = tx.serialize_base(ba); CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data"); return true; } //--------------------------------------------------------------- @@ -152,6 +188,7 @@ namespace cryptonote binary_archive<false> ba(ss); bool r = ::serialization::serialize(ba, tx); CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); tx.invalidate_hashes(); //TODO: validate tx diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 25e97f71f..95de6dc1e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -441,6 +441,53 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block()); m_db->block_txn_stop(); + uint64_t num_popped_blocks = 0; + while (true) + { + const uint64_t top_height = m_db->height() - 1; + const crypto::hash top_id = m_db->top_block_hash(); + const block top_block = m_db->get_top_block(); + const uint8_t ideal_hf_version = get_ideal_hard_fork_version(top_height); + if (ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version) + { + if (num_popped_blocks > 0) + MGINFO("Initial popping done, top block: " << top_id << ", top height: " << top_height << ", block version: " << (uint64_t)top_block.major_version); + break; + } + else + { + if (num_popped_blocks == 0) + MGINFO("Current top block " << top_id << " at height " << top_height << " has version " << (uint64_t)top_block.major_version << " which disagrees with the ideal version " << (uint64_t)ideal_hf_version); + if (num_popped_blocks % 100 == 0) + MGINFO("Popping blocks... " << top_height); + ++num_popped_blocks; + block popped_block; + std::vector<transaction> popped_txs; + try + { + m_db->pop_block(popped_block, popped_txs); + } + // anything that could cause this to throw is likely catastrophic, + // so we re-throw + catch (const std::exception& e) + { + MERROR("Error popping block from blockchain: " << e.what()); + throw; + } + catch (...) + { + MERROR("Error popping block from blockchain, throwing!"); + throw; + } + } + } + if (num_popped_blocks > 0) + { + m_timestamps_and_difficulties_height = 0; + m_hardfork->reorganize_from_chain_height(get_current_blockchain_height()); + m_tx_pool.on_blockchain_dec(m_db->height()-1, get_tail_id()); + } + update_next_cumulative_size_limit(); return true; } diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 17400ab68..ce75f74d8 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -650,39 +650,6 @@ namespace cryptonote return false; } - // resolve outPk references in rct txes - // outPk aren't the only thing that need resolving for a fully resolved tx, - // but outPk (1) are needed now to check range proof semantics, and - // (2) do not need access to the blockchain to find data - if (tx.version >= 2) - { - rct::rctSig &rv = tx.rct_signatures; - if (rv.outPk.size() != tx.vout.size()) - { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Bad outPk size in tx " << tx_hash << ", rejected"); - tvc.m_verifivation_failed = true; - return false; - } - for (size_t n = 0; n < tx.rct_signatures.outPk.size(); ++n) - rv.outPk[n].dest = rct::pk2rct(boost::get<txout_to_key>(tx.vout[n].target).key); - - const bool bulletproof = rv.type == rct::RCTTypeFullBulletproof || rv.type == rct::RCTTypeSimpleBulletproof; - if (bulletproof) - { - if (rv.p.bulletproofs.size() != tx.vout.size()) - { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Bad bulletproofs size in tx " << tx_hash << ", rejected"); - tvc.m_verifivation_failed = true; - return false; - } - for (size_t n = 0; n < rv.outPk.size(); ++n) - { - rv.p.bulletproofs[n].V.resize(1); - rv.p.bulletproofs[n].V[0] = rv.outPk[n].mask; - } - } - } - if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area()) { MTRACE("Skipping semantics check for tx kept by block in embedded hash area"); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d53ed82a9..6a37b59eb 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8201,14 +8201,14 @@ const wallet2::transfer_details &wallet2::get_transfer_details(size_t idx) const std::vector<size_t> wallet2::select_available_unmixable_outputs(bool trusted_daemon) { // request all outputs with less than 3 instances - const size_t min_mixin = use_fork_rules(6, 10) ? 4 : 2; // v6 increases min mixin from 2 to 4 + const size_t min_mixin = use_fork_rules(7, 10) ? 6 : use_fork_rules(6, 10) ? 4 : 2; // v6 increases min mixin from 2 to 4, v7 to 6 return select_available_outputs_from_histogram(min_mixin + 1, false, true, false, trusted_daemon); } //---------------------------------------------------------------------------------------------------- std::vector<size_t> wallet2::select_available_mixable_outputs(bool trusted_daemon) { // request all outputs with at least 3 instances, so we can use mixin 2 with - const size_t min_mixin = use_fork_rules(6, 10) ? 4 : 2; // v6 increases min mixin from 2 to 4 + const size_t min_mixin = use_fork_rules(7, 10) ? 6 : use_fork_rules(6, 10) ? 4 : 2; // v6 increases min mixin from 2 to 4, v7 to 6 return select_available_outputs_from_histogram(min_mixin + 1, true, true, true, trusted_daemon); } //---------------------------------------------------------------------------------------------------- diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 9c58536c9..249dbdbe8 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -103,6 +103,8 @@ if (NOT MSVC) COMPILE_FLAGS " -Wno-undef -Wno-sign-compare") endif () +SET_PROPERTY(SOURCE main.cpp PROPERTY COMPILE_FLAGS -DDEFAULT_DATA_DIR="\\"${CMAKE_SOURCE_DIR}/tests/data\\"") + SET_PROPERTY(SOURCE memwipe.cpp PROPERTY COMPILE_FLAGS -Ofast) add_test( diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index 507cec8cf..3e2199217 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -112,7 +112,7 @@ public: virtual bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const { return true; } virtual bool for_all_outputs(uint64_t amount, const std::function<bool(uint64_t height)> &f) const { return true; } virtual bool is_read_only() const { return false; } - virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const { return std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>(); } + virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const { return std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>(); } virtual void add_txpool_tx(const transaction &tx, const txpool_tx_meta_t& details) {} virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& details) {} diff --git a/tests/unit_tests/main.cpp b/tests/unit_tests/main.cpp index 85c6cbed5..13b62cbb4 100644 --- a/tests/unit_tests/main.cpp +++ b/tests/unit_tests/main.cpp @@ -61,8 +61,8 @@ int main(int argc, char** argv) ::testing::InitGoogleTest(&argc, argv); po::options_description desc_options("Command line options"); - const command_line::arg_descriptor<std::string> arg_data_dir = { "data-dir", "Data files directory" }; - command_line::add_arg(desc_options, arg_data_dir, ""); + const command_line::arg_descriptor<std::string> arg_data_dir = { "data-dir", "Data files directory", DEFAULT_DATA_DIR }; + command_line::add_arg(desc_options, arg_data_dir); po::variables_map vm; bool r = command_line::handle_error_helper(desc_options, [&]() @@ -74,12 +74,7 @@ int main(int argc, char** argv) if (! r) return 1; - if (command_line::is_arg_defaulted(vm, arg_data_dir)) - unit_test::data_dir = boost::filesystem::canonical(boost::filesystem::path(epee::string_tools::get_current_module_folder())) - .parent_path().parent_path().parent_path().parent_path() - .append("tests").append("data"); - else - unit_test::data_dir = command_line::get_arg(vm, arg_data_dir); + unit_test::data_dir = command_line::get_arg(vm, arg_data_dir); return RUN_ALL_TESTS(); } |