diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptonote_basic/connection_context.h | 1 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_defs.h | 2 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.h | 2 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.inl | 54 | ||||
-rw-r--r-- | src/cryptonote_protocol/levin_notify.cpp | 2 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 4 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 1 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 4 |
8 files changed, 65 insertions, 5 deletions
diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h index 8d26e5638..dfc59631f 100644 --- a/src/cryptonote_basic/connection_context.h +++ b/src/cryptonote_basic/connection_context.h @@ -69,6 +69,7 @@ namespace cryptonote bool m_anchor; int32_t m_score; int m_expect_response; + uint64_t m_expect_height; }; inline std::string get_protocol_state_string(cryptonote_connection_context::state s) diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index 9687b07a6..8c511e824 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -298,6 +298,7 @@ namespace cryptonote uint64_t cumulative_difficulty_top64; std::vector<crypto::hash> m_block_ids; std::vector<uint64_t> m_block_weights; + cryptonote::blobdata first_block; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(start_height) @@ -309,6 +310,7 @@ namespace cryptonote KV_SERIALIZE_OPT(cumulative_difficulty_top64, (uint64_t)0) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_ids) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_weights) + KV_SERIALIZE(first_block) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<request_t> request; diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 6368f8190..8f867eee6 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -117,6 +117,8 @@ namespace cryptonote std::string get_peers_overview() const; std::pair<uint32_t, uint32_t> get_next_needed_pruning_stripe() const; bool needs_new_sync_connections() const; + bool is_busy_syncing(); + private: //----------------- commands handlers ---------------------------------------------- int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 27f8888bb..e2598e382 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -141,6 +141,7 @@ namespace cryptonote { NOTIFY_REQUEST_CHAIN::request r = {}; context.m_needed_objects.clear(); + context.m_expect_height = m_core.get_current_blockchain_height(); m_core.get_short_chain_history(r.block_ids); handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?) r.prune = m_sync_pruned_blocks; @@ -493,6 +494,7 @@ namespace cryptonote context.m_needed_objects.clear(); context.m_state = cryptonote_connection_context::state_synchronizing; NOTIFY_REQUEST_CHAIN::request r = {}; + context.m_expect_height = m_core.get_current_blockchain_height(); m_core.get_short_chain_history(r.block_ids); r.prune = m_sync_pruned_blocks; handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?) @@ -773,6 +775,7 @@ namespace cryptonote context.m_needed_objects.clear(); context.m_state = cryptonote_connection_context::state_synchronizing; NOTIFY_REQUEST_CHAIN::request r = {}; + context.m_expect_height = m_core.get_current_blockchain_height(); m_core.get_short_chain_history(r.block_ids); handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?) r.prune = m_sync_pruned_blocks; @@ -1168,7 +1171,16 @@ namespace cryptonote return 1; } if (start_height == std::numeric_limits<uint64_t>::max()) + { start_height = boost::get<txin_gen>(b.miner_tx.vin[0]).height; + if (start_height > context.m_expect_height) + { + LOG_ERROR_CCONTEXT("sent block ahead of expected height, dropping connection"); + drop_connection(context, false, false); + ++m_sync_bad_spans_downloaded; + return 1; + } + } auto req_it = context.m_requested_objects.find(block_hash); if(req_it == context.m_requested_objects.end()) @@ -1714,6 +1726,7 @@ skip: LOG_PRINT_CCONTEXT_L2("requesting callback"); context.m_last_request_time = boost::date_time::not_a_date_time; context.m_expect_response = 0; + context.m_expect_height = 0; context.m_state = cryptonote_connection_context::state_standby; // we'll go back to adding, then (if we can't), download ++context.m_callback_request_count; m_p2p->request_callback(context); @@ -1813,6 +1826,16 @@ skip: LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN."); return 1; } + if (r.m_block_ids.size() >= 2) + { + cryptonote::block b; + if (!m_core.get_block_by_hash(r.m_block_ids[1], b)) + { + LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN: first block not found"); + return 1; + } + r.first_block = cryptonote::block_to_blob(b); + } MLOG_P2P_MESSAGE("-->>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()); post_notify<NOTIFY_RESPONSE_CHAIN_ENTRY>(r, context); return 1; @@ -2259,6 +2282,7 @@ skip: } } context.m_last_request_time = boost::posix_time::microsec_clock::universal_time(); + context.m_expect_height = span.first; context.m_expect_response = NOTIFY_RESPONSE_GET_OBJECTS::ID; MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size() << "requested blocks count=" << count << " / " << count_limit << " from " << span.first << ", first hash " << req.blocks.front()); @@ -2331,6 +2355,7 @@ skip: {//we have to fetch more objects ids, request blockchain entry NOTIFY_REQUEST_CHAIN::request r = {}; + context.m_expect_height = m_core.get_current_blockchain_height(); m_core.get_short_chain_history(r.block_ids); CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty"); @@ -2338,7 +2363,10 @@ skip: { // 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 != crypto::null_hash && r.block_ids.front() != context.m_last_known_hash) + { + context.m_expect_height = std::numeric_limits<uint64_t>::max(); r.block_ids.push_front(context.m_last_known_hash); + } } handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?) @@ -2480,6 +2508,12 @@ skip: return 1; } context.m_expect_response = 0; + if (arg.start_height + 1 > context.m_expect_height) // we expect an overlapping block + { + LOG_ERROR_CCONTEXT("Got NOTIFY_RESPONSE_CHAIN_ENTRY past expected height, dropping connection"); + drop_connection(context, true, false); + return 1; + } context.m_last_request_time = boost::date_time::not_a_date_time; @@ -2491,7 +2525,7 @@ skip: drop_connection(context, true, false); return 1; } - if (arg.total_height < arg.m_block_ids.size() || arg.start_height > arg.total_height - arg.m_block_ids.size() || arg.start_height >= m_core.get_current_blockchain_height()) + if (arg.total_height < arg.m_block_ids.size() || arg.start_height > arg.total_height - arg.m_block_ids.size()) { LOG_ERROR_CCONTEXT("sent invalid start/nblocks/height, dropping connection"); drop_connection(context, true, false); @@ -2527,6 +2561,17 @@ 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()) { @@ -2726,6 +2771,13 @@ skip: } //------------------------------------------------------------------------------------------------------------------------ template<class t_core> + bool t_cryptonote_protocol_handler<t_core>::is_busy_syncing() + { + const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock}; + return !sync.owns_lock(); + } + //------------------------------------------------------------------------------------------------------------------------ + template<class t_core> void t_cryptonote_protocol_handler<t_core>::drop_connection_with_score(cryptonote_connection_context &context, unsigned score, bool flush_all_spans) { LOG_DEBUG_CC(context, "dropping connection id " << context.m_connection_id << " (pruning seed " << diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp index 318bcf4e1..21363972d 100644 --- a/src/cryptonote_protocol/levin_notify.cpp +++ b/src/cryptonote_protocol/levin_notify.cpp @@ -287,7 +287,6 @@ namespace levin connection_count(0), flush_callbacks(0), nzone(zone), - is_public(is_public), pad_txs(pad_txs), fluffing(false) { @@ -305,7 +304,6 @@ namespace levin std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time std::uint32_t flush_callbacks; //!< Number of active fluff flush callbacks queued const epee::net_utils::zone nzone; //!< Zone is public ipv4/ipv6 connections, or i2p or tor - const bool is_public; //!< Zone is public ipv4/ipv6 connections const bool pad_txs; //!< Pad txs to the next boundary for privacy bool fluffing; //!< Zone is in Dandelion++ fluff epoch }; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 8000835c4..28001f6d5 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -804,6 +804,7 @@ namespace nodetool "zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083", }; } + return {}; case epee::net_utils::zone::i2p: if (m_nettype == cryptonote::MAINNET) { @@ -811,7 +812,8 @@ namespace nodetool "s3l6ke4ed3df466khuebb4poienoingwof7oxtbo6j4n56sghe3a.b32.i2p:18080", "sel36x6fibfzujwvt4hf5gxolz6kd3jpvbjqg6o3ud2xtionyl2q.b32.i2p:18080" }; - } + } + return {}; default: break; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 144ffe888..01735d62e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -499,6 +499,7 @@ namespace cryptonote res.update_available = restricted ? false : m_core.is_update_available(); res.version = restricted ? "" : MONERO_VERSION_FULL; res.synchronized = check_core_ready(); + res.busy_syncing = m_p2p.get_payload_object().is_busy_syncing(); res.status = CORE_RPC_STATUS_OK; return true; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 10f7aac7a..bb9005a5f 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -88,7 +88,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 3 -#define CORE_RPC_VERSION_MINOR 3 +#define CORE_RPC_VERSION_MINOR 4 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -684,6 +684,7 @@ namespace cryptonote bool was_bootstrap_ever_used; uint64_t database_size; bool update_available; + bool busy_syncing; std::string version; bool synchronized; @@ -724,6 +725,7 @@ namespace cryptonote KV_SERIALIZE(was_bootstrap_ever_used) KV_SERIALIZE(database_size) KV_SERIALIZE(update_available) + KV_SERIALIZE(busy_syncing) KV_SERIALIZE(version) KV_SERIALIZE(synchronized) END_KV_SERIALIZE_MAP() |