aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_protocol')
-rw-r--r--src/cryptonote_protocol/block_queue.cpp109
-rw-r--r--src/cryptonote_protocol/block_queue.h6
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_defs.h3
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl188
5 files changed, 144 insertions, 164 deletions
diff --git a/src/cryptonote_protocol/block_queue.cpp b/src/cryptonote_protocol/block_queue.cpp
index 583c3abf4..4f760582b 100644
--- a/src/cryptonote_protocol/block_queue.cpp
+++ b/src/cryptonote_protocol/block_queue.cpp
@@ -118,25 +118,6 @@ void block_queue::remove_spans(const boost::uuids::uuid &connection_id, uint64_t
}
}
-void block_queue::mark_last_block(uint64_t last_block_height)
-{
- boost::unique_lock<boost::recursive_mutex> lock(mutex);
- if (!blocks.empty() && is_blockchain_placeholder(*blocks.begin()))
- blocks.erase(*blocks.begin());
- for (block_map::iterator i = blocks.begin(); i != blocks.end(); )
- {
- block_map::iterator j = i++;
- if (j->start_block_height + j->nblocks - 1 <= last_block_height)
- {
- blocks.erase(j);
- }
- }
-
- // mark the current state of the db (for a fresh db, it's just the genesis block)
- add_blocks(0, last_block_height + 1, boost::uuids::nil_uuid());
- MDEBUG("last blocked marked at " << last_block_height);
-}
-
uint64_t block_queue::get_max_block_height() const
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
@@ -171,7 +152,19 @@ std::string block_queue::get_overview() const
return s;
}
-std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time)
+bool block_queue::requested(const crypto::hash &hash) const
+{
+ boost::unique_lock<boost::recursive_mutex> lock(mutex);
+ for (const auto &span: blocks)
+ {
+ for (const auto &h: span.hashes)
+ if (h == hash)
+ return true;
+ }
+ return false;
+}
+
+std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, const std::list<crypto::hash> &block_hashes, boost::posix_time::ptime time)
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
@@ -181,71 +174,27 @@ std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_hei
return std::make_pair(0, 0);
}
- uint64_t max_block_height = get_max_block_height();
- if (last_block_height > max_block_height)
- max_block_height = last_block_height;
- if (max_block_height == 0)
+ uint64_t span_start_height = last_block_height - block_hashes.size() + 1;
+ std::list<crypto::hash>::const_iterator i = block_hashes.begin();
+ while (i != block_hashes.end() && requested(*i))
{
- MDEBUG("reserve_span: max_block_height is 0");
- return std::make_pair(first_block_height, std::min(last_block_height - first_block_height + 1, max_blocks));
- }
-
- uint64_t base = 0, last_placeholder_block = 0;
- bool has_placeholder = false;
- block_map::const_iterator i = blocks.begin();
- if (i != blocks.end() && is_blockchain_placeholder(*i))
- {
- base = i->start_block_height + i->nblocks;
- last_placeholder_block = base - 1;
- has_placeholder = true;
++i;
- for (block_map::const_iterator j = i; j != blocks.end(); ++j)
- {
- if (j->start_block_height < base)
- base = j->start_block_height;
- }
+ ++span_start_height;
}
- if (base > first_block_height)
- base = first_block_height;
-
- CHECK_AND_ASSERT_MES (base <= max_block_height + 1, std::make_pair(0, 0), "Blockchain placeholder larger than max block height");
- std::vector<uint8_t> bitmap(max_block_height + 1 - base, 0);
- MDEBUG("base " << base << ", last_placeholder_block " << (has_placeholder ? std::to_string(last_placeholder_block) : "none") << ", first_block_height " << first_block_height);
- if (has_placeholder && last_placeholder_block >= base)
- memset(bitmap.data(), 1, last_placeholder_block + 1 - base);
- while (i != blocks.end())
+ uint64_t span_length = 0;
+ std::list<crypto::hash> hashes;
+ while (i != block_hashes.end() && span_length < max_blocks)
{
- CHECK_AND_ASSERT_MES (i->start_block_height >= base, std::make_pair(0, 0), "Span starts before blochckain placeholder");
- memset(bitmap.data() + i->start_block_height - base, 1, i->nblocks);
+ hashes.push_back(*i);
++i;
+ ++span_length;
}
-
- const uint8_t *ptr = (const uint8_t*)memchr(bitmap.data() + first_block_height - base, 0, bitmap.size() - (first_block_height - base));
- if (!ptr)
- {
- MDEBUG("reserve_span: 0 not found in bitmap: " << first_block_height << " " << bitmap.size());
- print();
- return std::make_pair(0, 0);
- }
- uint64_t start_block_height = ptr - bitmap.data() + base;
- if (start_block_height > last_block_height)
- {
- MDEBUG("reserve_span: start_block_height > last_block_height: " << start_block_height << " < " << last_block_height);
- return std::make_pair(0, 0);
- }
- if (start_block_height + max_blocks - 1 < first_block_height)
- {
- MDEBUG("reserve_span: start_block_height + max_blocks - 1 < first_block_height: " << start_block_height << " + " << max_blocks << " - 1 < " << first_block_height);
+ if (span_length == 0)
return std::make_pair(0, 0);
- }
-
- uint64_t nblocks = 1;
- while (start_block_height + nblocks <= last_block_height && nblocks < max_blocks && bitmap[start_block_height + nblocks - base] == 0)
- ++nblocks;
-
- MDEBUG("Reserving span " << start_block_height << " - " << (start_block_height + nblocks - 1) << " for " << connection_id);
- add_blocks(start_block_height, nblocks, connection_id, time);
- return std::make_pair(start_block_height, nblocks);
+ MDEBUG("Reserving span " << span_start_height << " - " << (span_start_height + span_length - 1) << " for " << connection_id);
+ add_blocks(span_start_height, span_length, connection_id, time);
+ set_span_hashes(span_start_height, connection_id, hashes);
+ return std::make_pair(span_start_height, span_length);
}
bool block_queue::is_blockchain_placeholder(const span &span) const
@@ -366,13 +315,15 @@ size_t block_queue::get_num_filled_spans() const
return size;
}
-crypto::hash block_queue::get_last_known_hash() const
+crypto::hash block_queue::get_last_known_hash(const boost::uuids::uuid &connection_id) const
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
crypto::hash hash = cryptonote::null_hash;
uint64_t highest_height = 0;
for (const auto &span: blocks)
{
+ if (span.connection_id != connection_id)
+ continue;
uint64_t h = span.start_block_height + span.nblocks - 1;
if (h > highest_height && span.hashes.size() == span.nblocks)
{
diff --git a/src/cryptonote_protocol/block_queue.h b/src/cryptonote_protocol/block_queue.h
index c75ebc0b9..9a211ac47 100644
--- a/src/cryptonote_protocol/block_queue.h
+++ b/src/cryptonote_protocol/block_queue.h
@@ -73,11 +73,10 @@ namespace cryptonote
void flush_stale_spans(const std::set<boost::uuids::uuid> &live_connections);
void remove_span(uint64_t start_block_height);
void remove_spans(const boost::uuids::uuid &connection_id, uint64_t start_block_height);
- void mark_last_block(uint64_t last_block_height);
uint64_t get_max_block_height() const;
void print() const;
std::string get_overview() const;
- std::pair<uint64_t, uint64_t> reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time());
+ std::pair<uint64_t, uint64_t> reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, const std::list<crypto::hash> &block_hashes, boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time());
bool is_blockchain_placeholder(const span &span) const;
std::pair<uint64_t, uint64_t> get_start_gap_span() const;
std::pair<uint64_t, uint64_t> get_next_span_if_scheduled(std::list<crypto::hash> &hashes, boost::uuids::uuid &connection_id, boost::posix_time::ptime &time) const;
@@ -86,9 +85,10 @@ namespace cryptonote
size_t get_data_size() const;
size_t get_num_filled_spans_prefix() const;
size_t get_num_filled_spans() const;
- crypto::hash get_last_known_hash() const;
+ crypto::hash get_last_known_hash(const boost::uuids::uuid &connection_id) const;
float get_speed(const boost::uuids::uuid &connection_id) const;
bool foreach(std::function<bool(const span&)> f, bool include_blockchain_placeholder = false) const;
+ bool requested(const crypto::hash &hash) const;
private:
block_map blocks;
diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h
index 37b503436..6e6c83f04 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_defs.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h
@@ -76,6 +76,8 @@ namespace cryptonote
boost::uuids::uuid connection_id;
+ uint64_t height;
+
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(incoming)
KV_SERIALIZE(localhost)
@@ -97,6 +99,7 @@ namespace cryptonote
KV_SERIALIZE(current_upload)
KV_SERIALIZE(support_flags)
KV_SERIALIZE_VAL_POD_AS_BLOB(connection_id)
+ KV_SERIALIZE(height)
END_KV_SERIALIZE_MAP()
};
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index dcee03f66..f30aebf3a 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -130,6 +130,8 @@ namespace cryptonote
size_t get_synchronizing_connections_count();
bool on_connection_synchronized();
bool should_download_next_span(cryptonote_connection_context& context) const;
+ void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
+
t_core& m_core;
nodetool::p2p_endpoint_stub<connection_context> m_p2p_stub;
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index d74937783..06a5356fe 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -239,6 +239,8 @@ namespace cryptonote
cnx.connection_id = cntxt.m_connection_id;
+ cnx.height = cntxt.m_remote_blockchain_height;
+
connections.push_back(cnx);
return true;
@@ -264,6 +266,8 @@ namespace cryptonote
return false;
}
+ context.m_remote_blockchain_height = hshd.current_height;
+
uint64_t target = m_core.get_target_blockchain_height();
if (target == 0)
target = m_core.get_current_blockchain_height();
@@ -293,7 +297,6 @@ namespace cryptonote
}
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;
//let the socket to send response to handshake, but request callback, to let send request data after response
LOG_PRINT_CCONTEXT_L2("requesting callback");
++context.m_callback_request_count;
@@ -341,10 +344,9 @@ namespace cryptonote
if(tvc.m_verifivation_failed)
{
LOG_PRINT_CCONTEXT_L1("Block verification failed: transaction verification failed, dropping connection");
- m_p2p->drop_connection(context);
+ drop_connection(context, false, false);
m_core.cleanup_handle_incoming_blocks();
m_core.resume_mine();
- m_block_queue.flush_spans(context.m_connection_id);
return 1;
}
}
@@ -356,9 +358,7 @@ namespace cryptonote
if(bvc.m_verifivation_failed)
{
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_host_fail(context.m_remote_address);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, true, false);
return 1;
}
if(bvc.m_added_to_main_chain)
@@ -411,8 +411,7 @@ namespace cryptonote
<< ", dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -445,8 +444,7 @@ namespace cryptonote
<< ", dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -460,8 +458,7 @@ namespace cryptonote
<< ", dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -485,8 +482,7 @@ namespace cryptonote
<< "dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -503,8 +499,7 @@ namespace cryptonote
if(!m_core.handle_incoming_tx(tx_blob, tvc, true, true, false) || tvc.m_verifivation_failed)
{
LOG_PRINT_CCONTEXT_L1("Block verification failed: transaction verification failed, dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -526,8 +521,7 @@ namespace cryptonote
<< ", dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -547,8 +541,7 @@ namespace cryptonote
<< ", dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
m_core.resume_mine();
return 1;
}
@@ -625,9 +618,7 @@ namespace cryptonote
if( bvc.m_verifivation_failed )
{
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_host_fail(context.m_remote_address);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, true, false);
return 1;
}
if( bvc.m_added_to_main_chain )
@@ -660,8 +651,7 @@ namespace cryptonote
);
m_core.resume_mine();
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -681,8 +671,7 @@ namespace cryptonote
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);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -709,8 +698,7 @@ namespace cryptonote
<< ", dropping connection"
);
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
}
@@ -721,16 +709,14 @@ namespace cryptonote
{
LOG_ERROR_CCONTEXT("Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, "
<< "failed to get requested transactions");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
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);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -773,8 +759,7 @@ namespace cryptonote
if(tvc.m_verifivation_failed)
{
LOG_PRINT_CCONTEXT_L1("Tx verification failed, dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
if(tvc.m_should_be_relayed)
@@ -800,8 +785,7 @@ namespace cryptonote
if(!m_core.handle_get_objects(arg, rsp, context))
{
LOG_ERROR_CCONTEXT("failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()=" << rsp.blocks.size() << ", txs.size()=" << rsp.txs.size()
@@ -868,8 +852,7 @@ namespace cryptonote
{
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height=" << arg.current_blockchain_height
<< " < m_last_response_height=" << context.m_last_response_height << ", dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -891,16 +874,14 @@ namespace cryptonote
{
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);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
if (b.miner_tx.vin.size() != 1 || b.miner_tx.vin.front().type() != typeid(txin_gen))
{
LOG_ERROR_CCONTEXT("sent wrong block: block: miner tx does not have exactly one txin_gen input"
<< epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
if (start_height == std::numeric_limits<uint64_t>::max())
@@ -912,16 +893,14 @@ namespace cryptonote
{
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
<< " wasn't requested, dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
if(b.tx_hashes.size() != block_entry.txs.size())
{
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
<< ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -933,8 +912,7 @@ namespace cryptonote
{
MERROR("returned not all requested objects (context.m_requested_objects.size()="
<< context.m_requested_objects.size() << "), dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -947,7 +925,8 @@ namespace cryptonote
}
{
- MLOG_YELLOW(el::Level::Debug, "Got NEW BLOCKS inside of " << __FUNCTION__ << ": size: " << arg.blocks.size());
+ MLOG_YELLOW(el::Level::Debug, context << " Got NEW BLOCKS inside of " << __FUNCTION__ << ": size: " << arg.blocks.size()
+ << ", blocks: " << start_height << " - " << (start_height + arg.blocks.size() - 1));
// add that new span to the block queue
const boost::posix_time::time_duration dt = now - context.m_last_request_time;
@@ -955,6 +934,8 @@ namespace cryptonote
MDEBUG(context << " adding span: " << arg.blocks.size() << " at height " << start_height << ", " << dt.total_microseconds()/1e6 << " seconds, " << (rate/1e3) << " kB/s, size now " << (m_block_queue.get_data_size() + blocks_size) / 1048576.f << " MB");
m_block_queue.add_blocks(start_height, arg.blocks, context.m_connection_id, rate, blocks_size);
+ context.m_last_known_hash = cryptonote::get_blob_hash(arg.blocks.back().block);
+
if (m_core.get_test_drop_download() && m_core.get_test_drop_download_height()) { // DISCARD BLOCKS for testing
// We try to lock the sync lock. If we can, it means no other thread is
@@ -978,7 +959,6 @@ namespace cryptonote
uint64_t start_height;
std::list<cryptonote::block_complete_entry> blocks;
boost::uuids::uuid span_connection_id;
- m_block_queue.mark_last_block(previous_height - 1);
if (!m_block_queue.get_next_span(start_height, blocks, span_connection_id))
{
MDEBUG(context << " no next span found, going back to download");
@@ -986,9 +966,41 @@ namespace cryptonote
}
MDEBUG(context << " next span in the queue has blocks " << start_height << "-" << (start_height + blocks.size() - 1)
<< ", we need " << previous_height);
- if (previous_height < start_height || previous_height >= start_height + blocks.size())
+
+
+ block new_block;
+ if (!parse_and_validate_block_from_blob(blocks.front().block, new_block))
{
- MDEBUG(context << " this span is not what we need, going back to download");
+ 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;
}
@@ -1019,8 +1031,7 @@ namespace cryptonote
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, tx_id = "
<< epee::string_tools::pod_to_hex(get_blob_hash(*it)) << ", dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id, true);
+ drop_connection(context, false, true);
return true;
}))
LOG_ERROR_CCONTEXT("span connection id not found");
@@ -1045,9 +1056,7 @@ namespace cryptonote
{
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_host_fail(context.m_remote_address);
- m_block_queue.flush_spans(context.m_connection_id, true);
+ drop_connection(context, true, true);
return true;
}))
LOG_ERROR_CCONTEXT("span connection id not found");
@@ -1061,9 +1070,7 @@ namespace cryptonote
{
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
LOG_PRINT_CCONTEXT_L1("Block received at sync phase was marked as orphaned, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_host_fail(context.m_remote_address);
- m_block_queue.flush_spans(context.m_connection_id, true);
+ drop_connection(context, true, true);
return true;
}))
LOG_ERROR_CCONTEXT("span connection id not found");
@@ -1083,7 +1090,7 @@ namespace cryptonote
m_core.cleanup_handle_incoming_blocks();
- m_block_queue.mark_last_block(m_core.get_current_blockchain_height() - 1);
+ m_block_queue.remove_spans(span_connection_id, start_height);
if (m_core.get_current_blockchain_height() > previous_height)
{
@@ -1113,8 +1120,7 @@ skip:
if (!request_missing_objects(context, true, force_next_span))
{
LOG_ERROR_CCONTEXT("Failed to request missing objects, dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
return 1;
@@ -1134,8 +1140,7 @@ skip:
if(!m_core.find_blockchain_supplement(arg.block_ids, r))
{
LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN.");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size());
@@ -1201,8 +1206,6 @@ skip:
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::request_missing_objects(cryptonote_connection_context& context, bool check_having_blocks, bool force_next_span)
{
- m_block_queue.mark_last_block(m_core.get_current_blockchain_height() - 1);
-
// flush stale spans
std::set<boost::uuids::uuid> live_connections;
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool{
@@ -1308,8 +1311,13 @@ skip:
context.m_last_response_height = 0;
goto skip;
}
+ // take out blocks we already have
+ while (!context.m_needed_objects.empty() && m_core.have_block(context.m_needed_objects.front()))
+ {
+ context.m_needed_objects.pop_front();
+ }
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
- span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id);
+ span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_needed_objects);
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
}
if (span.second == 0 && !force_next_span)
@@ -1360,8 +1368,6 @@ skip:
auto j = it++;
context.m_needed_objects.erase(j);
}
-
- m_block_queue.set_span_hashes(span.first, context.m_connection_id, hashes);
}
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
@@ -1384,10 +1390,9 @@ skip:
if (!start_from_current_chain)
{
- // we'll want to start off from where we are on the download side, which may not be added yet
- crypto::hash last_known_hash = m_block_queue.get_last_known_hash();
- if (last_known_hash != cryptonote::null_hash && r.block_ids.front() != last_known_hash)
- r.block_ids.push_front(last_known_hash);
+ // we'll want to start off from where we are on that peer, which may not be added yet
+ if (context.m_last_known_hash != cryptonote::null_hash && r.block_ids.front() != context.m_last_known_hash)
+ r.block_ids.push_front(context.m_last_known_hash);
}
handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
@@ -1464,9 +1469,7 @@ skip:
if(!arg.m_block_ids.size())
{
LOG_ERROR_CCONTEXT("sent empty m_block_ids, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_host_fail(context.m_remote_address);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, true, false);
return 1;
}
@@ -1477,8 +1480,7 @@ skip:
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);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
@@ -1490,8 +1492,7 @@ skip:
if (!request_missing_objects(context, false))
{
LOG_ERROR_CCONTEXT("Failed to request missing objects, dropping connection");
- m_p2p->drop_connection(context);
- m_block_queue.flush_spans(context.m_connection_id);
+ drop_connection(context, false, false);
return 1;
}
return 1;
@@ -1547,6 +1548,29 @@ skip:
m_core.on_transaction_relayed(*tx_blob_it);
return relay_post_notify<NOTIFY_NEW_TRANSACTIONS>(arg, exclude_context);
}
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
+ void t_cryptonote_protocol_handler<t_core>::drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans)
+ {
+ if (add_fail)
+ m_p2p->add_host_fail(context.m_remote_address);
+ m_p2p->drop_connection(context);
+
+ uint64_t target = 0;
+ m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id, uint32_t support_flags) {
+ if (cntxt.m_state >= cryptonote_connection_context::state_synchronizing && cntxt.m_connection_id != context.m_connection_id)
+ target = std::max(target, cntxt.m_remote_blockchain_height);
+ return true;
+ });
+ const uint64_t previous_target = m_core.get_target_blockchain_height();
+ if (target < previous_target)
+ {
+ MINFO("Target height decreasing from " << previous_target << " to " << target);
+ m_core.set_target_blockchain_height(target);
+ }
+
+ m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
+ }
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>