From 3da1edfde573d7ff21f9c2f986046e4d5c026259 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 15 Aug 2017 16:54:08 +0100 Subject: [PATCH] cryptonote_protocol: fix out of order addition This was broken by the reorg fix, since we now have to add blocks regardless of their starting height. We now check whether we know the parent for the first block in the next span, or whether it was requested. If neither, it's an orphan. If it is not known, but was requested, we wait to get that block. --- .../cryptonote_protocol_handler.inl | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index b5a307208..e9dcd135f 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -990,6 +990,43 @@ namespace cryptonote MDEBUG(context << " next span in the queue has blocks " << start_height << "-" << (start_height + blocks.size() - 1) << ", we need " << previous_height); + + block new_block; + if (!parse_and_validate_block_from_blob(blocks.front().block, new_block)) + { + MERROR("Failed to parse block, but it should already have been parsed"); + break; + } + bool parent_known = m_core.have_block(new_block.prev_id); + if (!parent_known) + { + // it could be: + // - later in the current chain + // - later in an alt chain + // - orphan + // if it was requested, then it'll be resolved later, otherwise it's an orphan + bool parent_requested = false; + m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool{ + if (context.m_requested_objects.find(new_block.prev_id) != context.m_requested_objects.end()) + { + parent_requested = true; + return false; + } + return true; + }); + if (!parent_requested) + { + LOG_ERROR_CCONTEXT("Got block with unknown parent which was not requested - dropping connection"); + // in case the peer had dropped beforehand, remove the span anyway so other threads can wake up and get it + m_block_queue.remove_spans(span_connection_id, start_height); + return 1; + } + + // parent was requested, so we wait for it to be retrieved + MINFO(context << " parent was requested, we'll get back to it"); + break; + } + const boost::posix_time::ptime start = boost::posix_time::microsec_clock::universal_time(); m_core.prepare_handle_incoming_blocks(blocks);