From 10489fd2a7a10d4183f85122d6a256470ab83999 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Tue, 30 Jun 2020 20:30:50 +0200 Subject: [PATCH 1/7] Handle errors when preparing incoming blocks --- .../cryptonote_protocol_handler.inl | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 38154f0bf..a07518777 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -354,7 +354,13 @@ namespace cryptonote m_core.pause_mine(); std::list blocks; blocks.push_back(arg.b); - m_core.prepare_handle_incoming_blocks(blocks); + if (!m_core.prepare_handle_incoming_blocks(blocks)) + { + LOG_PRINT_CCONTEXT_L1("Block verification failed: prepare_handle_incoming_blocks failed, dropping connection"); + drop_connection(context, false, false); + m_core.resume_mine(); + return 1; + } for(auto tx_blob_it = arg.b.txs.begin(); tx_blob_it!=arg.b.txs.end();tx_blob_it++) { cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); @@ -629,7 +635,12 @@ namespace cryptonote std::list blocks; blocks.push_back(b); - m_core.prepare_handle_incoming_blocks(blocks); + if (!m_core.prepare_handle_incoming_blocks(blocks)) + { + LOG_PRINT_CCONTEXT_L0("Failure in prepare_handle_incoming_blocks"); + m_core.resume_mine(); + return 1; + } block_verification_context bvc = boost::value_initialized(); m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block @@ -1075,7 +1086,11 @@ skip: const boost::posix_time::ptime start = boost::posix_time::microsec_clock::universal_time(); context.m_last_request_time = start; - m_core.prepare_handle_incoming_blocks(blocks); + if (!m_core.prepare_handle_incoming_blocks(blocks)) + { + LOG_ERROR_CCONTEXT("Failure in prepare_handle_incoming_blocks"); + return 1; + } uint64_t block_process_time_full = 0, transactions_process_time_full = 0; size_t num_txs = 0; From 226b0e808ab8240fb17b43b3d09e9570f92307ba Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sat, 4 Jul 2020 13:47:47 +0200 Subject: [PATCH 2/7] Don't select minimal amount for purchase --- src/wallet/wallet.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c11a0f3f7..f3b980d50 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -9128,6 +9128,9 @@ std::vector wallet::create_transactions_advanced(safex::comm { pop_if_present(*unused_token_transfers_indices, idx); } + else if (dsts[0].output_type == tx_out_type::out_safex_purchase) { + idx = pop_best_value(unused_cash_transfers_indices->empty() ? *unused_cash_dust_indices : *unused_cash_transfers_indices, tx.selected_transfers, false, tx_out_type::out_cash); + } else if (needed_cash > 0) { pop_if_present(*unused_cash_transfers_indices, idx); @@ -9228,7 +9231,7 @@ std::vector wallet::create_transactions_advanced(safex::comm if(purchase_init) continue; purchase_init = true; - idx = pop_best_value(unused_cash_transfers_indices->empty() ? *unused_cash_dust_indices : *unused_cash_transfers_indices, tx.selected_transfers, true, tx_out_type::out_cash); + idx = pop_best_value(unused_cash_transfers_indices->empty() ? *unused_cash_dust_indices : *unused_cash_transfers_indices, tx.selected_transfers, false, tx_out_type::out_cash); } } From 33b4954ef087b99b57688e055ba6933b02251720 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Wed, 8 Jul 2020 11:43:37 +0200 Subject: [PATCH 3/7] Fix for rating print in simplewallet callback --- src/simplewallet/simplewallet_safex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet_safex.cpp b/src/simplewallet/simplewallet_safex.cpp index 8d530740e..c674c2662 100644 --- a/src/simplewallet/simplewallet_safex.cpp +++ b/src/simplewallet/simplewallet_safex.cpp @@ -1650,7 +1650,7 @@ namespace cryptonote tr("Height ") << height << ", " << tr("txid ") << txid << ", " << tr("Feedback sent received for offer: ") << feedback.offer_id << " received, " << - tr("Stars given: ") << feedback.stars_given << ", " << + tr("Stars given: ") << (uint64_t)feedback.stars_given << ", " << tr("Comment given: ") << comment << ", " << tr("idx ") << subaddr_index; From 390317f6b60aee54b20aeea484d4d54cde4a114a Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Fri, 10 Jul 2020 16:15:11 +0200 Subject: [PATCH 4/7] Proper fix for sweep_unmixable --- src/wallet/wallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f3b980d50..967a9f3ce 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -10067,7 +10067,7 @@ std::vector wallet::create_unmixable_sweep_transactions(bool std::vector unmixable_transfer_outputs, unmixable_dust_outputs; for (auto n: unmixable_outputs) { - if (!m_transfers[n].m_token_transfer) + if (m_transfers[n].get_out_type() == cryptonote::tx_out_type::out_cash) { if (m_transfers[n].amount() < fee_per_kb) unmixable_dust_outputs.push_back(n); @@ -10090,7 +10090,7 @@ std::vector wallet::create_unmixable_sweep_transactions(bool for (auto n: unmixable_token_outputs) { - if (m_transfers[n].m_token_transfer) + if (m_transfers[n].get_out_type() == cryptonote::tx_out_type::out_token) { if (m_transfers[n].token_amount() < fee_per_kb) unmixable_token_dust_outputs.push_back(n); @@ -10115,7 +10115,7 @@ std::vector wallet::create_unmixable_sweep_transactions(bool std::vector mixable_transfer_outputs, mixable_dust_outputs; for (auto n: mixable_outputs) { - if (!m_transfers[n].m_token_transfer) + if (m_transfers[n].get_out_type() == cryptonote::tx_out_type::out_cash) { if (m_transfers[n].amount() < fee_per_kb) mixable_dust_outputs.push_back(n); From 93902f68fb964efe81a01870b0b88fee859539a9 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 13 Jul 2020 11:30:13 +0200 Subject: [PATCH 5/7] Better logic for purchase cash selection --- src/wallet/wallet.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 967a9f3ce..8e481bbd3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -9187,6 +9187,10 @@ std::vector wallet::create_transactions_advanced(safex::comm { idx = pop_best_value(*unused_token_transfers_indices, tx.selected_transfers, true, tx_out_type::out_token); } + else if(command_type == safex::command_t::simple_purchase && !purchase_init) { + purchase_init = true; + idx = pop_best_value(unused_cash_transfers_indices->empty() ? *unused_cash_dust_indices : *unused_cash_transfers_indices, tx.selected_transfers, false, tx_out_type::out_cash); + } else if (needed_cash > 0) { idx = pop_best_value(unused_cash_transfers_indices->empty() ? *unused_cash_dust_indices : *unused_cash_transfers_indices, tx.selected_transfers, true, tx_out_type::out_cash); @@ -9227,12 +9231,6 @@ std::vector wallet::create_transactions_advanced(safex::comm //find price peg output idx = pop_advanced_output(tx.selected_transfers, price_peg.price_peg_id, tx_out_type::out_safex_price_peg); } - else if(command_type == safex::command_t::simple_purchase && needed_cash == 0) { - if(purchase_init) - continue; - purchase_init = true; - idx = pop_best_value(unused_cash_transfers_indices->empty() ? *unused_cash_dust_indices : *unused_cash_transfers_indices, tx.selected_transfers, false, tx_out_type::out_cash); - } } From 3f29d71e4379515c65be68f4bdfd8d31ce5fa9c9 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Thu, 23 Jul 2020 11:24:32 +0200 Subject: [PATCH 6/7] Fix build for newer GCC --- src/cryptonote_core/blockchain.cpp | 88 ------------------------------ src/cryptonote_core/blockchain.h | 87 ++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 91 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 36ef16ec6..a5034a277 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -2550,94 +2550,6 @@ uint64_t Blockchain::block_difficulty(uint64_t i) const return 0; } //------------------------------------------------------------------ -//TODO: return type should be void, throw on exception -// alternatively, return true only if no blocks missed -template -bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const -{ - LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); - - for (const auto& block_hash : block_ids) - { - try - { - blocks.push_back(std::make_pair(m_db->get_block_blob(block_hash), block())); - if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second)) - { - LOG_ERROR("Invalid block"); - return false; - } - } - catch (const BLOCK_DNE& e) - { - missed_bs.push_back(block_hash); - } - catch (const std::exception& e) - { - return false; - } - } - return true; -} -//------------------------------------------------------------------ -//TODO: return type should be void, throw on exception -// alternatively, return true only if no transactions missed -template -bool Blockchain::get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const -{ - LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); - - for (const auto& tx_hash : txs_ids) - { - try - { - cryptonote::blobdata tx = AUTO_VAL_INIT(tx); - if (m_db->get_tx_blob(tx_hash, tx)) - txs.push_back(std::move(tx)); - else - missed_txs.push_back(tx_hash); - } - catch (const std::exception& e) - { - return false; - } - } - return true; -} -//------------------------------------------------------------------ -template -bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const -{ - LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); - - for (const auto& tx_hash : txs_ids) - { - try - { - cryptonote::blobdata tx = AUTO_VAL_INIT(tx); - if (m_db->get_tx_blob(tx_hash, tx)) - { - txs.push_back(transaction()); - if (!parse_and_validate_tx_from_blob(tx, txs.back())) - { - LOG_ERROR("Invalid transaction"); - return false; - } - } - else - missed_txs.push_back(tx_hash); - } - catch (const std::exception& e) - { - return false; - } - } - return true; -} -//------------------------------------------------------------------ // Find the split point between us and foreign blockchain and return // (by reference) the most recent common block hash along with up to // BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes. diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 012904f31..9445ec9e9 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -734,8 +734,37 @@ namespace cryptonote * * @return false if an unexpected exception occurs, else true */ + //------------------------------------------------------------------ + //TODO: return type should be void, throw on exception + // alternatively, return true only if no blocks missed template - bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const; + bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const + { + LOG_PRINT_L3("Blockchain::" << __func__); + CRITICAL_REGION_LOCAL(m_blockchain_lock); + + for (const auto& block_hash : block_ids) + { + try + { + blocks.push_back(std::make_pair(m_db->get_block_blob(block_hash), block())); + if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second)) + { + LOG_ERROR("Invalid block"); + return false; + } + } + catch (const BLOCK_DNE& e) + { + missed_bs.push_back(block_hash); + } + catch (const std::exception& e) + { + return false; + } + } + return true; + } /** * @brief gets transactions based on a list of transaction hashes @@ -749,10 +778,62 @@ namespace cryptonote * * @return false if an unexpected exception occurs, else true */ + //TODO: return type should be void, throw on exception + // alternatively, return true only if no transactions missed template - bool get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const; + bool get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const + { + LOG_PRINT_L3("Blockchain::" << __func__); + CRITICAL_REGION_LOCAL(m_blockchain_lock); + + for (const auto& tx_hash : txs_ids) + { + try + { + cryptonote::blobdata tx = AUTO_VAL_INIT(tx); + if (m_db->get_tx_blob(tx_hash, tx)) + txs.push_back(std::move(tx)); + else + missed_txs.push_back(tx_hash); + } + catch (const std::exception& e) + { + return false; + } + } + return true; + } + //------------------------------------------------------------------ template - bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const; + bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const + { + LOG_PRINT_L3("Blockchain::" << __func__); + CRITICAL_REGION_LOCAL(m_blockchain_lock); + + for (const auto& tx_hash : txs_ids) + { + try + { + cryptonote::blobdata tx = AUTO_VAL_INIT(tx); + if (m_db->get_tx_blob(tx_hash, tx)) + { + txs.push_back(transaction()); + if (!parse_and_validate_tx_from_blob(tx, txs.back())) + { + LOG_ERROR("Invalid transaction"); + return false; + } + } + else + missed_txs.push_back(tx_hash); + } + catch (const std::exception& e) + { + return false; + } + } + return true; + } //debug functions From 8184371d7ed7915517c360eac19cf2d3e4e5d29d Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Thu, 23 Jul 2020 19:03:29 +0200 Subject: [PATCH 7/7] Resolve endless circle of dependecies --- src/cryptonote_basic/miner.cpp | 10 +++++----- src/cryptonote_basic/miner.h | 8 ++++---- src/cryptonote_core/cryptonote_core.cpp | 4 +++- src/cryptonote_core/cryptonote_tx_utils.cpp | 4 +++- src/safex/CMakeLists.txt | 3 --- tests/core_tests/chaingen.cpp | 8 ++++++-- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index e2eabef09..382a66660 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -98,13 +98,13 @@ namespace cryptonote } - miner::miner(i_miner_handler* phandler, Blockchain* pbc):m_stop(1), + miner::miner(i_miner_handler* phandler, const get_block_hash_t &gbh):m_stop(1), m_template(boost::value_initialized()), m_template_no(0), m_diffic(0), m_thread_index(0), m_phandler(phandler), - m_pbc(pbc), + m_gbh(gbh), m_height(0), m_pausers_count(0), m_threads_total(0), @@ -382,12 +382,12 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------------- - bool miner::find_nonce_for_given_block(const Blockchain *pbc, block& bl, const difficulty_type& diffic, uint64_t height) + bool miner::find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height) { for(; bl.nonce != std::numeric_limits::max(); bl.nonce++) { crypto::hash h; - get_block_longhash(pbc, bl, h, height, tools::get_max_concurrency()); + gbh(bl, height, tools::get_max_concurrency(), h); if(check_hash(h, diffic)) { @@ -485,7 +485,7 @@ namespace cryptonote b.nonce = nonce; crypto::hash h; - get_block_longhash(m_pbc, b, h, height, tools::get_max_concurrency()); + m_gbh(b, height, tools::get_max_concurrency(), h); if(check_hash(h, local_diff)) { diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index ff9fae291..2b956751f 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -57,7 +57,7 @@ namespace cryptonote ~i_miner_handler(){}; }; - class Blockchain; + typedef std::function get_block_hash_t; /************************************************************************/ /* */ @@ -65,7 +65,7 @@ namespace cryptonote class miner { public: - miner(i_miner_handler* phandler, Blockchain* pbc); + miner(i_miner_handler* phandler, const get_block_hash_t& gbh); ~miner(); bool init(const boost::program_options::variables_map& vm, network_type nettype); static void init_options(boost::program_options::options_description& desc); @@ -81,7 +81,7 @@ namespace cryptonote bool on_idle(); void on_synchronized(); //synchronous analog (for fast calls) - static bool find_nonce_for_given_block(const Blockchain *pbc, block& bl, const difficulty_type& diffic, uint64_t height); + static bool find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height); void pause(); void resume(); void do_print_hashrate(bool do_hr); @@ -137,7 +137,7 @@ namespace cryptonote std::list m_threads; epee::critical_section m_threads_lock; i_miner_handler* m_phandler; - Blockchain* m_pbc; + get_block_hash_t m_gbh; account_public_address m_mine_address; epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval; epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 6ab904732..1ca6d3813 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -168,7 +168,9 @@ namespace cryptonote core::core(i_cryptonote_protocol* pprotocol): m_mempool(m_blockchain_storage), m_blockchain_storage(m_mempool), - m_miner(this, &m_blockchain_storage), + m_miner(this, [this](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash) { + return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, threads); + }), m_miner_address(boost::value_initialized()), m_starter_message_showed(false), m_target_blockchain_height(0), diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index ac527f80c..bd9762642 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -1819,7 +1819,9 @@ namespace cryptonote bl.invalidate_hashes(); bl.timestamp = 0; bl.nonce = nonce; - miner::find_nonce_for_given_block(NULL, bl, 1, 0); + miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash){ + return cryptonote::get_block_longhash(NULL, b, hash, height, threads); + }, bl, 1, 0); return true; } //--------------------------------------------------------------- diff --git a/src/safex/CMakeLists.txt b/src/safex/CMakeLists.txt index 1a1625697..6e5f514e0 100644 --- a/src/safex/CMakeLists.txt +++ b/src/safex/CMakeLists.txt @@ -64,10 +64,7 @@ safex_add_library(safex_core target_link_libraries(safex_core PUBLIC - blockchain_db - cryptonote_core cncrypto common - cryptonote_protocol PRIVATE ${EXTRA_LIBRARIES}) diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index b8077a626..f87215751 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -184,7 +184,9 @@ bool test_generator::construct_block(cryptonote::block& blk, uint64_t height, co // Nonce search... blk.nonce = 0; - while (!miner::find_nonce_for_given_block(NULL, blk, get_test_difficulty(), height)) + while (!miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash){ + return cryptonote::get_block_longhash(NULL, b, hash, height, threads); + }, blk, get_test_difficulty(), height)) blk.timestamp++; const uint8_t hf_version = 1; //hardcode hf version for tests @@ -1622,7 +1624,9 @@ void fill_update_price_peg_sources_and_destinations(const std::vector