diff options
Diffstat (limited to 'src/cryptonote_protocol/cryptonote_protocol_handler.inl')
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.inl | 182 |
1 files changed, 134 insertions, 48 deletions
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 1309ff742..79578a34e 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -2,7 +2,7 @@ /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) /// @brief This is the orginal cryptonote protocol network-events handler, modified by us -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -39,7 +39,7 @@ #include <list> #include <unordered_map> -#include "cryptonote_core/cryptonote_format_utils.h" +#include "cryptonote_basic/cryptonote_format_utils.h" #include "profile_tools.h" #include "../../src/p2p/network_throttle-detail.hpp" @@ -265,19 +265,24 @@ namespace cryptonote if(context.m_state == cryptonote_connection_context::state_synchronizing) return true; + uint64_t target = m_core.get_target_blockchain_height(); + if (target == 0) + target = m_core.get_current_blockchain_height(); + if(m_core.have_block(hshd.top_id)) { context.m_state = cryptonote_connection_context::state_normal; - if(is_inital) + if(is_inital && target == m_core.get_current_blockchain_height()) on_connection_synchronized(); return true; } + if (hshd.current_height > target) + { /* As I don't know if accessing hshd from core could be a good practice, I prefer pushing target height to the core at the same time it is pushed to the user. Nz. */ m_core.set_target_blockchain_height(static_cast<int64_t>(hshd.current_height)); - int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height()); int64_t max_block_height = max(static_cast<int64_t>(hshd.current_height),static_cast<int64_t>(m_core.get_current_blockchain_height())); int64_t last_block_v1 = 1009826; @@ -286,6 +291,7 @@ namespace cryptonote << " [Your node is " << std::abs(diff) << " blocks (" << ((abs(diff) - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) " << (0 <= diff ? std::string("behind") : std::string("ahead")) << "] " << ENDL << "SYNCHRONIZATION started"); + } LOG_PRINT_L1("Remote blockchain height: " << hshd.current_height << ", id: " << hshd.top_id); context.m_state = cryptonote_connection_context::state_synchronizing; context.m_remote_blockchain_height = hshd.current_height; @@ -367,7 +373,7 @@ namespace cryptonote template<class t_core> int t_cryptonote_protocol_handler<t_core>::handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context) { - MLOG_P2P_MESSAGE("Received NOTIFY_NEW_FLUFFY_BLOCK (hop " << arg.hop << ", " << arg.b.txs.size() << " txes)"); + MLOG_P2P_MESSAGE("Received NOTIFY_NEW_FLUFFY_BLOCK (height " << arg.current_blockchain_height << ", hop " << arg.hop << ", " << arg.b.txs.size() << " txes)"); if(context.m_state != cryptonote_connection_context::state_normal) return 1; @@ -377,7 +383,7 @@ namespace cryptonote transaction miner_tx; if(parse_and_validate_block_from_blob(arg.b.block, new_block)) { - // This is a seccond notification, we must have asked for some missing tx + // This is a second notification, we must have asked for some missing tx if(!context.m_requested_objects.empty()) { // What we asked for != to what we received .. @@ -475,6 +481,7 @@ namespace cryptonote // sent in our pool, so don't verify again.. if(!m_core.get_pool_transaction(tx_hash, tx)) { + MDEBUG("Incoming tx " << tx_hash << " not in pool, adding"); cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); if(!m_core.handle_incoming_tx(tx_blob, tvc, true, true, false) || tvc.m_verifivation_failed) { @@ -496,9 +503,9 @@ namespace cryptonote { LOG_ERROR_CCONTEXT ( - "sent wrong tx: failed to parse and validate transaction: \r\n" + "sent wrong tx: failed to parse and validate transaction: " << epee::string_tools::buff_to_hex_nodelimer(tx_blob) - << "\r\n dropping connection" + << ", dropping connection" ); m_p2p->drop_connection(context); @@ -535,7 +542,28 @@ namespace cryptonote } else { - need_tx_indices.push_back(tx_idx); + std::vector<crypto::hash> tx_ids; + std::list<transaction> txes; + std::list<crypto::hash> missing; + tx_ids.push_back(tx_hash); + if (m_core.get_transactions(tx_ids, txes, missing) && missing.empty()) + { + if (txes.size() == 1) + { + have_tx.push_back(tx_to_blob(txes.front())); + } + else + { + MERROR("1 tx requested, none not found, but " << txes.size() << " returned"); + m_core.resume_mine(); + return 1; + } + } + else + { + MDEBUG("Tx " << tx_hash << " not found in pool"); + need_tx_indices.push_back(tx_idx); + } } ++tx_idx; @@ -544,8 +572,11 @@ namespace cryptonote if(!need_tx_indices.empty()) // drats, we don't have everything.. { // request non-mempool txs + MDEBUG("We are missing " << need_tx_indices.size() << " txes for this fluffy block"); + for (auto txidx: need_tx_indices) + MDEBUG(" tx " << new_block.tx_hashes[txidx]); NOTIFY_REQUEST_FLUFFY_MISSING_TX::request missing_tx_req; - missing_tx_req.b = arg.b; + missing_tx_req.block_hash = get_block_hash(new_block); missing_tx_req.hop = arg.hop; missing_tx_req.current_blockchain_height = arg.current_blockchain_height; missing_tx_req.missing_tx_indices = std::move(need_tx_indices); @@ -555,6 +586,8 @@ namespace cryptonote } else // whoo-hoo we've got em all .. { + MDEBUG("We have all needed txes for this fluffy block"); + block_complete_entry b; b.block = arg.b.block; b.txs = have_tx; @@ -581,7 +614,7 @@ namespace cryptonote NOTIFY_NEW_BLOCK::request reg_arg = AUTO_VAL_INIT(reg_arg); reg_arg.hop = arg.hop; reg_arg.current_blockchain_height = arg.current_blockchain_height; - reg_arg.b.block = b.block; + reg_arg.b = b; relay_block(reg_arg, context); } else if( bvc.m_marked_as_orphaned ) @@ -598,9 +631,9 @@ namespace cryptonote { LOG_ERROR_CCONTEXT ( - "sent wrong block: failed to parse and validate block: \r\n" + "sent wrong block: failed to parse and validate block: " << epee::string_tools::buff_to_hex_nodelimer(arg.b.block) - << "\r\n dropping connection" + << ", dropping connection" ); m_core.resume_mine(); @@ -615,34 +648,32 @@ namespace cryptonote template<class t_core> int t_cryptonote_protocol_handler<t_core>::handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context) { - MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_FLUFFY_MISSING_TX (" << arg.missing_tx_indices.size() << " txes)"); + MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_FLUFFY_MISSING_TX (" << arg.missing_tx_indices.size() << " txes), block hash " << arg.block_hash); - std::list<block> local_blocks; - std::list<transaction> local_txs; - if(!m_core.get_blocks(arg.current_blockchain_height - 1, 1, local_blocks, local_txs)) - { + std::list<std::pair<cryptonote::blobdata, block>> local_blocks; + std::list<cryptonote::blobdata> local_txs; - LOG_ERROR_CCONTEXT - ( - "Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX" - << ", get_blocks( start_offset = " << (arg.current_blockchain_height - 1) << " ) failed" - << ", dropping connection" - ); - + block b; + if (!m_core.get_block_by_hash(arg.block_hash, b)) + { + LOG_ERROR_CCONTEXT("failed to find block: " << arg.block_hash << ", dropping connection"); m_p2p->drop_connection(context); - return 1; + return 1; } + for (auto txidx: arg.missing_tx_indices) + MDEBUG(" tx " << b.tx_hashes[txidx]); + + std::vector<crypto::hash> txids; NOTIFY_NEW_FLUFFY_BLOCK::request fluffy_response; - fluffy_response.b = arg.b; - fluffy_response.current_blockchain_height = m_core.get_current_blockchain_height(); + fluffy_response.b.block = t_serializable_object_to_blob(b); + fluffy_response.current_blockchain_height = arg.current_blockchain_height; fluffy_response.hop = arg.hop; - size_t local_txs_count = local_txs.size(); for(auto& tx_idx: arg.missing_tx_indices) { - if(tx_idx < local_txs_count) + if(tx_idx < b.tx_hashes.size()) { - fluffy_response.b.txs.push_back(t_serializable_object_to_blob( *(std::next(local_txs.begin(), tx_idx)) )); + txids.push_back(b.tx_hashes[tx_idx]); } else { @@ -650,7 +681,8 @@ namespace cryptonote ( "Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX" << ", request is asking for a tx whose index is out of bounds " - << ", tx index = " << tx_idx << ", block_height = " << arg.current_blockchain_height + << ", tx index = " << tx_idx << ", block tx count " << b.tx_hashes.size() + << ", block_height = " << arg.current_blockchain_height << ", dropping connection" ); @@ -658,7 +690,29 @@ namespace cryptonote return 1; } } - + + std::list<cryptonote::transaction> txs; + std::list<crypto::hash> missed; + if (!m_core.get_transactions(txids, txs, missed)) + { + LOG_ERROR_CCONTEXT("Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, " + << "failed to get requested transactions"); + m_p2p->drop_connection(context); + return 1; + } + if (!missed.empty() || txs.size() != txids.size()) + { + LOG_ERROR_CCONTEXT("Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, " + << missed.size() << " requested transactions not found" << ", dropping connection"); + m_p2p->drop_connection(context); + return 1; + } + + for(auto& tx: txs) + { + fluffy_response.b.txs.push_back(t_serializable_object_to_blob(tx)); + } + LOG_PRINT_CCONTEXT_L2 ( "-->>NOTIFY_RESPONSE_FLUFFY_MISSING_TX: " @@ -790,6 +844,8 @@ namespace cryptonote context.m_remote_blockchain_height = arg.current_blockchain_height; size_t count = 0; + std::vector<crypto::hash> block_hashes; + block_hashes.reserve(arg.blocks.size()); for(const block_complete_entry& block_entry: arg.blocks) { if (m_stopping) @@ -801,15 +857,16 @@ namespace cryptonote block b; if(!parse_and_validate_block_from_blob(block_entry.block, b)) { - LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n" - << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection"); + LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: " + << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection"); m_p2p->drop_connection(context); return 1; } //to avoid concurrency in core between connections, suspend connections which delivered block later then first one + const crypto::hash block_hash = get_block_hash(b); if(count == 2) { - if(m_core.have_block(get_block_hash(b))) + if(m_core.have_block(block_hash)) { context.m_state = cryptonote_connection_context::state_idle; context.m_needed_objects.clear(); @@ -819,7 +876,7 @@ namespace cryptonote } } - auto req_it = context.m_requested_objects.find(get_block_hash(b)); + auto req_it = context.m_requested_objects.find(block_hash); if(req_it == context.m_requested_objects.end()) { LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) @@ -836,6 +893,7 @@ namespace cryptonote } context.m_requested_objects.erase(req_it); + block_hashes.push_back(block_hash); } if(context.m_requested_objects.size()) @@ -848,17 +906,44 @@ namespace cryptonote { - m_core.pause_mine(); - epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler( - boost::bind(&t_core::resume_mine, &m_core)); - MLOG_YELLOW(el::Level::Debug, "Got NEW BLOCKS inside of " << __FUNCTION__ << ": size: " << arg.blocks.size()); if (m_core.get_test_drop_download() && m_core.get_test_drop_download_height()) { // DISCARD BLOCKS for testing - uint64_t previous_height = m_core.get_current_blockchain_height(); + // we lock all the rest to avoid having multiple connections redo a lot + // of the same work, and one of them doing it for nothing: subsequent + // connections will wait until the current one's added its blocks, then + // will add any extra it has, if any + CRITICAL_REGION_LOCAL(m_sync_lock); + + m_core.pause_mine(); + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler( + boost::bind(&t_core::resume_mine, &m_core)); + + const uint64_t previous_height = m_core.get_current_blockchain_height(); + + // dismiss what another connection might already have done (likely everything) + uint64_t top_height; + crypto::hash top_hash; + if (m_core.get_blockchain_top(top_height, top_hash)) { + uint64_t dismiss = 1; + for (const auto &h: block_hashes) { + if (top_hash == h) { + LOG_DEBUG_CC(context, "Found current top block in synced blocks, dismissing " + << dismiss << "/" << arg.blocks.size() << " blocks"); + while (dismiss--) + arg.blocks.pop_front(); + break; + } + ++dismiss; + } + } + + if (arg.blocks.empty()) + goto skip; m_core.prepare_handle_incoming_blocks(arg.blocks); + for(const block_complete_entry& block_entry: arg.blocks) { if (m_stopping) @@ -875,7 +960,7 @@ namespace cryptonote m_core.handle_incoming_tx(tx_blob, tvc, true, true, false); if(tvc.m_verifivation_failed) { - LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = " + LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, tx_id = " << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection"); m_p2p->drop_connection(context); m_core.cleanup_handle_incoming_blocks(); @@ -922,6 +1007,7 @@ namespace cryptonote } +skip: request_missing_objects(context, true); return 1; } @@ -1071,9 +1157,9 @@ namespace cryptonote context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1; if(context.m_last_response_height > context.m_remote_blockchain_height) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with \r\nm_total_height=" << arg.total_height - << "\r\nm_start_height=" << arg.start_height - << "\r\nm_block_ids.size()=" << arg.m_block_ids.size()); + LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with m_total_height=" << arg.total_height + << ", m_start_height=" << arg.start_height + << ", m_block_ids.size()=" << arg.m_block_ids.size()); m_p2p->drop_connection(context); } @@ -1110,12 +1196,12 @@ namespace cryptonote { if(m_core.get_testnet() && (support_flags & P2P_SUPPORT_FLAG_FLUFFY_BLOCKS)) { - MDEBUG("PEER SUPPORTS FLUFFY BLOCKS - RELAYING THIN/COMPACT WHATEVER BLOCK"); + LOG_DEBUG_CC(context, "PEER SUPPORTS FLUFFY BLOCKS - RELAYING THIN/COMPACT WHATEVER BLOCK"); fluffyConnections.push_back(context.m_connection_id); } else { - MDEBUG("PEER DOESN'T SUPPORT FLUFFY BLOCKS - RELAYING FULL BLOCK"); + LOG_DEBUG_CC(context, "PEER DOESN'T SUPPORT FLUFFY BLOCKS - RELAYING FULL BLOCK"); fullConnections.push_back(context.m_connection_id); } } |