aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_protocol')
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl64
1 files changed, 52 insertions, 12 deletions
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index e0f856f1b..5dbd02da8 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -2570,17 +2570,6 @@ skip:
return 1;
}
- std::unordered_set<crypto::hash> hashes;
- for (const auto &h: arg.m_block_ids)
- {
- if (!hashes.insert(h).second)
- {
- LOG_ERROR_CCONTEXT("sent duplicate block, dropping connection");
- drop_connection(context, true, false);
- return 1;
- }
- }
-
uint64_t n_use_blocks = m_core.prevalidate_block_hashes(arg.start_height, arg.m_block_ids, arg.m_block_weights);
if (n_use_blocks == 0 || n_use_blocks + HASH_OF_HASHES_STEP <= arg.m_block_ids.size())
{
@@ -2592,18 +2581,69 @@ skip:
context.m_needed_objects.clear();
uint64_t added = 0;
std::unordered_set<crypto::hash> blocks_found;
+ bool first = true;
+ bool expect_unknown = false;
for (size_t i = 0; i < arg.m_block_ids.size(); ++i)
{
if (!blocks_found.insert(arg.m_block_ids[i]).second)
{
LOG_ERROR_CCONTEXT("Duplicate blocks in chain entry response, dropping connection");
- drop_connection(context, true, false);
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ int where;
+ const bool have_block = m_core.have_block_unlocked(arg.m_block_ids[i], &where);
+ if (first && !have_block)
+ {
+ LOG_ERROR_CCONTEXT("First block hash is unknown, dropping connection");
+ drop_connection_with_score(context, 5, false);
return 1;
}
+ if (!first)
+ {
+ // after the first, blocks may be known or unknown, but if they are known,
+ // they should be at the same height if on the main chain
+ if (have_block)
+ {
+ switch (where)
+ {
+ default:
+ case HAVE_BLOCK_INVALID:
+ LOG_ERROR_CCONTEXT("Block is invalid or known without known type, dropping connection");
+ drop_connection(context, true, false);
+ return 1;
+ case HAVE_BLOCK_MAIN_CHAIN:
+ if (expect_unknown)
+ {
+ LOG_ERROR_CCONTEXT("Block is on the main chain, but we did not expect a known block, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ if (m_core.get_block_id_by_height(arg.start_height + i) != arg.m_block_ids[i])
+ {
+ LOG_ERROR_CCONTEXT("Block is on the main chain, but not at the expected height, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ break;
+ case HAVE_BLOCK_ALT_CHAIN:
+ if (expect_unknown)
+ {
+ LOG_ERROR_CCONTEXT("Block is on the main chain, but we did not expect a known block, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ break;
+ }
+ }
+ else
+ expect_unknown = true;
+ }
const uint64_t block_weight = arg.m_block_weights.empty() ? 0 : arg.m_block_weights[i];
context.m_needed_objects.push_back(std::make_pair(arg.m_block_ids[i], block_weight));
if (++added == n_use_blocks)
break;
+ first = false;
}
context.m_last_response_height -= arg.m_block_ids.size() - n_use_blocks;