diff options
-rw-r--r-- | contrib/epee/include/net/net_utils_base.h | 10 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.h | 1 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.inl | 32 |
3 files changed, 36 insertions, 7 deletions
diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index cfa51e10d..76f247e83 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -159,11 +159,11 @@ inline MAKE_LOGGABLE(connection_context_base, ct, os) #define LOG_TRACE_CC(ct, message) MTRACE(ct << message) #define LOG_CC(level, ct, message) MLOG(level, ct << message) -#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(epee::net_utils::print_connection_context_short(ct) << message) -#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(epee::net_utils::print_connection_context_short(ct) << message) -#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(epee::net_utils::print_connection_context_short(ct) << message) -#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(epee::net_utils::print_connection_context_short(ct) << message) -#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(epee::net_utils::print_connection_context_short(ct) << message) +#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(ct << message) +#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(ct << message) +#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(ct << message) +#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(ct << message) +#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(ct << message) #define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message) #define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 7a3a2d325..fd4f03690 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -135,6 +135,7 @@ namespace cryptonote std::atomic<bool> m_synchronized; bool m_one_request = true; std::atomic<bool> m_stopping; + epee::critical_section m_sync_lock; boost::mutex m_buffer_mutex; double get_avg_block_size(); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 3c72733a4..72940d36a 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -826,6 +826,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) @@ -843,9 +845,10 @@ namespace cryptonote 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(); @@ -855,7 +858,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)) @@ -872,6 +875,7 @@ namespace cryptonote } context.m_requested_objects.erase(req_it); + block_hashes.push_back(block_hash); } if(context.m_requested_objects.size()) @@ -894,7 +898,31 @@ namespace cryptonote 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); + + // 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; + } + } + m_core.prepare_handle_incoming_blocks(arg.blocks); + for(const block_complete_entry& block_entry: arg.blocks) { if (m_stopping) |