38#include <boost/optional/optional.hpp>
49#undef MONERO_DEFAULT_LOG_CATEGORY
50#define MONERO_DEFAULT_LOG_CATEGORY "net.cn"
52#define MLOG_P2P_MESSAGE(x) MCINFO("net.p2p.msg", context << x)
53#define MLOGIF_P2P_MESSAGE(init, test, x) \
55 const auto level = el::Level::Info; \
56 const char *cat = "net.p2p.msg"; \
57 if (ELPP->vRegistry()->allowed(level, cat)) { \
61 el::base::Writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(cat) << str; \
66#define MLOG_PEER_STATE(x) \
67 MCINFO(MONERO_DEFAULT_LOG_CATEGORY, context << "[" << epee::string_tools::to_string_hex(context.m_pruning_seed) << "] state: " << x << " in state " << cryptonote::get_protocol_state_string(context.m_state))
69#define BLOCK_QUEUE_NSPANS_THRESHOLD 10
70#define BLOCK_QUEUE_SIZE_THRESHOLD (100*1024*1024)
71#define BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS 1000
72#define REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD_STANDBY (5 * 1000000)
73#define REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD (30 * 1000000)
74#define IDLE_PEER_KICK_TIME (240 * 1000000)
75#define NON_RESPONSIVE_PEER_KICK_TIME (20 * 1000000)
76#define PASSIVE_PEER_KICK_TIME (60 * 1000000)
77#define DROP_ON_SYNC_WEDGE_THRESHOLD (30 * 1000000000ull)
78#define LAST_ACTIVITY_STALL_THRESHOLD (2.0f)
79#define DROP_PEERS_ON_SCORE -2
83 template <
class CryptoHashContainer>
85 const std::vector<cryptonote::tx_blob_entry>& tx_entries,
86 const CryptoHashContainer& blk_tx_hashes,
87 const bool allow_pruned,
92 if (tx_entries.size() > blk_tx_hashes.size())
94 MERROR(
"Failed to make pool supplement: Too many transaction blobs!");
102 MERROR(
"Transaction blob of length " << tx_entry.blob.size() <<
" is too large to unpack!");
107 if (is_pruned && !allow_pruned)
109 MERROR(
"Pruned transaction not allowed here");
115 bool parse_success =
false;
128 MERROR(
"failed to parse and/or validate transaction: "
133 else if (!blk_tx_hashes.count(tx_hash))
135 MERROR(
"transaction " << tx_hash <<
" not in block");
152 MERROR(
"sent bad block: failed to parse and/or validate block: "
160 if (blk_tx_hashes.size() != blk_entry.
txs.size())
162 MERROR(
"sent bad block entry: number of hashes is not equal number of tx blobs: "
169 MERROR(
"sent bad block entry: there are duplicate tx hashes in parsed block: "
181 template<
class t_core>
184 m_syncronized_connections_count(0),
185 m_synchronized(offline),
186 m_ask_for_txpool_complement(
true),
195 template<
class t_core>
198 m_sync_timer.pause();
199 m_sync_timer.reset();
202 m_last_add_end_time = 0;
203 m_sync_spans_downloaded = 0;
204 m_sync_old_spans_downloaded = 0;
205 m_sync_bad_spans_downloaded = 0;
206 m_sync_download_chain_size = 0;
207 m_sync_download_objects_size = 0;
215 template<
class t_core>
221 template<
class t_core>
230 template<
class t_core>
234 CHECK_AND_ASSERT_MES_CC( context.m_callback_request_count > 0,
false,
"false callback fired, but context.m_callback_request_count=" << context.m_callback_request_count);
235 --context.m_callback_request_count;
238 if (context.m_idle_peer_notification.compare_exchange_strong(notified, not notified))
242 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
243 const boost::posix_time::time_duration dt = now - context.m_last_request_time;
244 const auto ms = dt.total_microseconds();
247 if (context.m_score-- >= 0)
249 MINFO(context <<
" kicking idle peer, last update " << (dt.total_microseconds() / 1.e6) <<
" seconds ago, expecting " << (
int)context.m_expect_response);
250 context.m_last_request_time = boost::date_time::not_a_date_time;
251 context.m_expect_response = 0;
252 context.m_expect_height = 0;
253 context.m_requested_objects.clear();
258 MINFO(context <<
"dropping idle peer with negative score");
259 drop_connection_with_score(context, context.m_expect_response == 0 ? 1 : 5,
false);
267 if (context.m_new_stripe_notification.compare_exchange_strong(notified, not notified))
276 context.m_needed_objects.clear();
277 m_core.get_short_chain_history(r.block_ids, context.m_expect_height);
278 handler_request_blocks_history( r.block_ids );
279 r.prune = m_sync_pruned_blocks;
280 context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
282 MLOG_P2P_MESSAGE(
"-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
283 post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
289 try_add_next_blocks(context);
295 template<
class t_core>
298 std::stringstream ss;
301 double down_sum = 0.0;
302 double down_curr_sum = 0.0;
304 double up_curr_sum = 0.0;
306 ss << std::setw(30) << std::left <<
"Remote Host"
307 << std::setw(20) <<
"Peer id"
308 << std::setw(20) <<
"Support Flags"
309 << std::setw(30) <<
"Recv/Sent (inactive,sec)"
310 << std::setw(25) <<
"State"
311 << std::setw(20) <<
"Livetime(sec)"
312 << std::setw(12) <<
"Down (kB/s)"
313 << std::setw(14) <<
"Down(now)"
314 << std::setw(10) <<
"Up (kB/s)"
315 << std::setw(13) <<
"Up(now)"
321 auto connection_time = time(NULL) - cntxt.
m_started;
322 ss << std::setw(30) << std::left << std::string(cntxt.
m_is_income ?
" [INC]":
"[OUT]") +
325 << std::setw(20) << std::hex << support_flags
326 << std::setw(30) << std::to_string(cntxt.
m_recv_cnt)+
"(" + std::to_string(time(NULL) - cntxt.
m_last_recv) +
")" +
"/" + std::to_string(cntxt.
m_send_cnt) +
"(" + std::to_string(time(NULL) - cntxt.
m_last_send) +
")"
328 << std::setw(20) << std::to_string(time(NULL) - cntxt.
m_started)
329 << std::setw(12) << std::fixed << (connection_time == 0 ? 0.0 : cntxt.
m_recv_cnt / connection_time / 1024)
331 << std::setw(10) << std::fixed << (connection_time == 0 ? 0.0 : cntxt.
m_send_cnt / connection_time / 1024)
333 << (local_ip ?
"[LAN]" :
"")
337 if (connection_time > 1)
339 down_sum += (cntxt.
m_recv_cnt / connection_time / 1024);
340 up_sum += (cntxt.
m_send_cnt / connection_time / 1024);
349 << std::setw(125) <<
" "
350 << std::setw(12) << down_sum
351 << std::setw(14) << down_curr_sum
352 << std::setw(10) << up_sum
353 << std::setw(13) << up_curr_sum
355 LOG_PRINT_L0(
"Connections: " << ENDL << ss.str());
360 template<
class t_core>
363 std::list<connection_info> connections;
368 auto timestamp = time(NULL);
401 auto connection_time = time(NULL) - cntxt.
m_started;
402 if (connection_time == 0)
424 connections.push_back(cnx);
432 template<
class t_core>
448 MDEBUG(context <<
" peer claims higher version than we think (" <<
450 ") - we may be forked from the network and a software upgrade may be needed, or that peer is broken or malicious");
468 MINFO(context <<
"Claims " << hshd.
current_height <<
", claimed " << context.m_remote_blockchain_height <<
" before");
469 hit_score(context, 1);
474 uint64_t target = m_core.get_target_blockchain_height();
476 target = m_core.get_current_blockchain_height();
478 if(m_core.have_block(hshd.
top_id))
480 context.set_state_normal();
481 if(is_inital && hshd.
current_height >= target && target == m_core.get_current_blockchain_height())
482 on_connection_synchronized();
489 context.set_state_normal();
499 uint64_t abs_diff = std::abs(diff);
500 uint64_t max_block_height = std::max(hshd.
current_height,m_core.get_current_blockchain_height());
501 uint64_t last_block_v1 = m_core.get_nettype() ==
TESTNET ? 624633 : m_core.get_nettype() ==
MAINNET ? 1009826 : (
uint64_t)-1;
502 uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0;
505 << (0 <= diff ? std::string(
"behind") : std::string(
"ahead"))
506 <<
"] " << ENDL <<
"SYNCHRONIZATION started");
507 if (hshd.
current_height >= m_core.get_current_blockchain_height() + 5)
509 m_core.safesyncmode(
false);
511 if (m_core.get_target_blockchain_height() == 0)
513 m_sync_timer.resume();
514 m_sync_timer.reset();
517 m_last_add_end_time = 0;
518 m_sync_spans_downloaded = 0;
519 m_sync_old_spans_downloaded = 0;
520 m_sync_bad_spans_downloaded = 0;
521 m_sync_download_chain_size = 0;
522 m_sync_download_objects_size = 0;
526 MINFO(context <<
"Remote blockchain height: " << hshd.
current_height <<
", id: " << hshd.
top_id);
530 context.set_state_normal();
537 ++context.m_callback_request_count;
538 m_p2p->request_callback(context);
540 context.m_num_requested = 0;
544 template<
class t_core>
550 hshd.
cumulative_difficulty = (wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
553 hshd.
pruning_seed = m_core.get_blockchain_pruning_seed();
557 template<
class t_core>
561 get_payload_sync_data(hsd);
566 template<
class t_core>
575 fluffy_arg.b = std::move(arg.b);
576 fluffy_arg.current_blockchain_height = arg.current_blockchain_height;
577 return handle_notify_new_fluffy_block(command, fluffy_arg, context);
580 template<
class t_core>
586 if(!is_synchronized())
588 LOG_DEBUG_CC(context,
"Received new block while syncing, ignored");
593 if (!m_core.check_incoming_block_size(arg.b.block))
595 drop_connection(context,
false,
false);
606 "sent wrong block: failed to parse and validate block: "
608 <<
", dropping connection"
611 drop_connection(context,
false,
false);
616 MLOG_P2P_MESSAGE(context <<
"Received NOTIFY_NEW_FLUFFY_BLOCK " << new_block_hash <<
" (height "
617 << arg.current_blockchain_height <<
", " << arg.b.txs.size() <<
" txes)");
630 std::unordered_map<crypto::hash, uint64_t> blk_txids_set;
631 for (
size_t tx_idx = 0; tx_idx < new_block.
tx_hashes.size(); ++tx_idx)
632 blk_txids_set.emplace(new_block.
tx_hashes[tx_idx], tx_idx);
635 if (blk_txids_set.size() != new_block.
tx_hashes.size())
637 MERROR(
"sent bad block entry: there are duplicate tx hashes in parsed block: "
639 drop_connection(context,
false,
false);
652 "Failed to parse one or more transactions in fluffy block with ID " << new_block_hash <<
653 ", dropping connection"
656 drop_connection(context,
false,
false);
662 const bool handle_block_res = m_core.handle_single_incoming_block(arg.b.block,
681 std::vector<uint64_t> need_tx_indices;
682 need_tx_indices.reserve(new_block.
tx_hashes.size());
685 for (
size_t tx_idx = 0; tx_idx < new_block.
tx_hashes.size(); ++tx_idx)
689 std::vector<cryptonote::blobdata> tx_blobs;
690 std::vector<crypto::hash> missed_txs;
692 bool need_tx = !m_core.pool_has_tx(tx_hash);
693 need_tx = need_tx && (!m_core.get_transactions({tx_hash}, tx_blobs, missed_txs,
true)
694 || !missed_txs.empty());
697 need_tx_indices.push_back(tx_idx);
701 MDEBUG(
"We are missing " << need_tx_indices.size() <<
" txes for this fluffy block");
702 for (
auto txidx: need_tx_indices)
703 MDEBUG(
" tx " << new_block.
tx_hashes[txidx]);
705 missing_tx_req.block_hash = new_block_hash;
706 missing_tx_req.current_blockchain_height = arg.current_blockchain_height;
707 missing_tx_req.missing_tx_indices = std::move(need_tx_indices);
710 MLOG_P2P_MESSAGE(
"-->>NOTIFY_REQUEST_FLUFFY_MISSING_TX: missing_tx_indices.size()=" << missing_tx_req.missing_tx_indices.size() );
711 post_notify<NOTIFY_REQUEST_FLUFFY_MISSING_TX>(missing_tx_req, context);
725 relay_block(arg, context);
729 context.m_needed_objects.clear();
732 m_core.get_short_chain_history(r.block_ids, context.m_expect_height);
733 handler_request_blocks_history( r.block_ids );
734 r.prune = m_sync_pruned_blocks;
735 context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
737 MLOG_P2P_MESSAGE(
"-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
738 post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
744 CHECK_AND_ASSERT_MES(m_core.update_checkpoints(), 1,
"One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
749 template<
class t_core>
752 MLOG_P2P_MESSAGE(
"Received NOTIFY_REQUEST_FLUFFY_MISSING_TX (" << arg.missing_tx_indices.size() <<
" txes), block hash " << arg.block_hash);
756 drop_connection(context,
false,
false);
760 std::vector<std::pair<cryptonote::blobdata, block>> local_blocks;
761 std::vector<cryptonote::blobdata> local_txs;
764 if (!m_core.get_block_by_hash(arg.block_hash,
b))
766 LOG_ERROR_CCONTEXT(
"failed to find block: " << arg.block_hash <<
", dropping connection");
767 drop_connection(context,
false,
false);
771 std::vector<crypto::hash> txids;
775 fluffy_response.current_blockchain_height = arg.current_blockchain_height;
776 std::vector<bool> seen(
b.
tx_hashes.size(),
false);
777 for(
auto& tx_idx: arg.missing_tx_indices)
786 "Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX"
787 <<
", request is asking for duplicate tx "
788 <<
", tx index = " << tx_idx <<
", block tx count " <<
b.
tx_hashes.size()
789 <<
", block_height = " << arg.current_blockchain_height
790 <<
", dropping connection"
792 drop_connection(context,
true,
false);
802 "Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX"
803 <<
", request is asking for a tx whose index is out of bounds "
804 <<
", tx index = " << tx_idx <<
", block tx count " <<
b.
tx_hashes.size()
805 <<
", block_height = " << arg.current_blockchain_height
806 <<
", dropping connection"
809 drop_connection(context,
false,
false);
814 std::vector<cryptonote::transaction> txs;
815 std::vector<crypto::hash> missed;
816 if (!m_core.get_transactions(txids, txs, missed))
819 <<
"failed to get requested transactions");
820 drop_connection(context,
false,
false);
823 if (!missed.empty() || txs.size() != txids.size())
826 << missed.size() <<
" requested transactions not found" <<
", dropping connection");
827 drop_connection(context,
false,
false);
838 "-->>NOTIFY_RESPONSE_FLUFFY_MISSING_TX: "
839 <<
", txs.size()=" << fluffy_response.b.txs.size()
840 <<
", rsp.current_blockchain_height=" << fluffy_response.current_blockchain_height
843 post_notify<NOTIFY_NEW_FLUFFY_BLOCK>(fluffy_response, context);
847 template<
class t_core>
850 MLOG_P2P_MESSAGE(
"Received NOTIFY_GET_TXPOOL_COMPLEMENT (" << arg.hashes.size() <<
" txes)");
854 std::vector<std::pair<cryptonote::blobdata, block>> local_blocks;
855 std::vector<cryptonote::blobdata> local_txs;
857 std::vector<cryptonote::blobdata> txes;
858 if (!m_core.get_txpool_complement(arg.hashes, txes))
865 new_txes.txs = std::move(txes);
869 "-->>NOTIFY_NEW_TRANSACTIONS: "
870 <<
", txs.size()=" << new_txes.txs.size()
873 post_notify<NOTIFY_NEW_TRANSACTIONS>(new_txes, context);
877 template<
class t_core>
880 MLOG_P2P_MESSAGE(
"Received NOTIFY_NEW_TRANSACTIONS (" << arg.txs.size() <<
" txes)");
881 std::unordered_set<blobdata> seen;
882 for (
const auto &blob: arg.txs)
885 if (seen.find(blob) != seen.end())
888 drop_connection(context,
false,
false);
900 if(!is_synchronized())
902 LOG_DEBUG_CC(context,
"Received new tx while syncing, ignored");
919 std::vector<blobdata> stem_txs{};
920 std::vector<blobdata> fluff_txs{};
921 if (arg.dandelionpp_fluff)
924 fluff_txs.reserve(arg.txs.size());
927 stem_txs.reserve(arg.txs.size());
929 for (
auto&
tx : arg.txs)
932 if (!m_core.handle_incoming_tx(
tx, tvc,
tx_relay,
true) && !tvc.m_no_drop_offense)
935 drop_connection(context,
false,
false);
943 stem_txs.push_back(std::move(
tx));
947 fluff_txs.push_back(std::move(
tx));
956 if (!stem_txs.empty())
959 arg.dandelionpp_fluff =
false;
960 arg.txs = std::move(stem_txs);
961 relay_transactions(arg, context.m_connection_id, context.m_remote_address.get_zone(),
relay_method::stem);
963 if (!fluff_txs.empty())
966 arg.dandelionpp_fluff =
true;
967 arg.txs = std::move(fluff_txs);
968 relay_transactions(arg, context.m_connection_id, context.m_remote_address.get_zone(),
relay_method::fluff);
973 template<
class t_core>
979 drop_connection(context,
false,
false);
982 MLOG_P2P_MESSAGE(
"Received NOTIFY_REQUEST_GET_OBJECTS (" << arg.blocks.size() <<
" blocks)");
986 "Requested objects count is too big ("
987 << arg.blocks.size() <<
") expected not more then "
989 drop_connection(context,
false,
false);
994 if(!m_core.handle_get_objects(arg, rsp, context))
996 LOG_ERROR_CCONTEXT(
"failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection");
997 drop_connection(context,
false,
false);
1000 context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
1002 << rsp.blocks.size() <<
", rsp.m_current_blockchain_height=" << rsp.current_blockchain_height
1003 <<
", missed_ids.size()=" << rsp.missed_ids.size());
1004 post_notify<NOTIFY_RESPONSE_GET_OBJECTS>(rsp, context);
1012 template<
class t_core>
1016 if (m_avg_buffer.empty()) {
1017 MWARNING(
"m_avg_buffer.size() == 0");
1021 for (
const auto &element : m_avg_buffer) avg += element;
1022 return avg / m_avg_buffer.size();
1025 template<
class t_core>
1028 MLOG_P2P_MESSAGE(
"Received NOTIFY_RESPONSE_GET_OBJECTS (" << arg.blocks.size() <<
" blocks)");
1031 boost::posix_time::ptime request_time = context.m_last_request_time;
1032 context.m_last_request_time = boost::date_time::not_a_date_time;
1036 LOG_ERROR_CCONTEXT(
"Got NOTIFY_RESPONSE_GET_OBJECTS out of the blue, dropping connection");
1037 drop_connection(context,
true,
false);
1040 context.m_expect_response = 0;
1044 size_t blocks_size = 0;
1045 for (
const auto &element : arg.blocks) {
1046 blocks_size += element.block.size();
1047 for (
const auto &
tx : element.txs)
1048 blocks_size +=
tx.blob.size();
1050 size += blocks_size;
1052 for (
const auto &element : arg.missed_ids)
1053 size +=
sizeof(element.data);
1055 size +=
sizeof(arg.current_blockchain_height);
1058 m_avg_buffer.push_back(size);
1060 ++m_sync_spans_downloaded;
1061 m_sync_download_objects_size += size;
1062 MDEBUG(context <<
" downloaded " << size <<
" bytes worth of blocks");
1071 if(arg.blocks.empty())
1074 drop_connection(context,
true,
false);
1075 ++m_sync_bad_spans_downloaded;
1078 if(context.m_last_response_height > arg.current_blockchain_height)
1080 LOG_ERROR_CCONTEXT(
"sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height=" << arg.current_blockchain_height
1081 <<
" < m_last_response_height=" << context.m_last_response_height <<
", dropping connection");
1082 drop_connection(context,
false,
false);
1083 ++m_sync_bad_spans_downloaded;
1087 if (arg.current_blockchain_height < context.m_remote_blockchain_height)
1089 MINFO(context <<
"Claims " << arg.current_blockchain_height <<
", claimed " << context.m_remote_blockchain_height <<
" before");
1090 hit_score(context, 1);
1092 context.m_remote_blockchain_height = arg.current_blockchain_height;
1093 if (context.m_remote_blockchain_height > m_core.get_target_blockchain_height())
1094 m_core.set_target_blockchain_height(context.m_remote_blockchain_height);
1096 std::vector<crypto::hash> block_hashes;
1097 block_hashes.reserve(arg.blocks.size());
1098 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
1099 uint64_t start_height = std::numeric_limits<uint64_t>::max();
1102 for(std::size_t i = 0; i < arg.blocks.size(); ++i)
1114 drop_connection(context,
false,
false);
1115 ++m_sync_bad_spans_downloaded;
1120 LOG_ERROR_CCONTEXT(
"sent wrong block: block: miner tx does not have exactly one txin_gen input"
1122 drop_connection(context,
false,
false);
1123 ++m_sync_bad_spans_downloaded;
1127 const auto this_height = boost::get<txin_gen>(
b.
miner_tx.
vin[0]).height;
1128 if (context.get_expected_hash(this_height) != block_hash)
1131 drop_connection(context,
false,
false);
1132 ++m_sync_bad_spans_downloaded;
1137 if (start_height == std::numeric_limits<uint64_t>::max())
1139 start_height = this_height;
1140 if (start_height > context.m_expect_height)
1143 drop_connection(context,
false,
false);
1144 ++m_sync_bad_spans_downloaded;
1148 if (this_height == 0 || context.get_expected_hash(this_height - 1) !=
b.
prev_id)
1151 drop_connection(context,
false,
false);
1152 ++m_sync_bad_spans_downloaded;
1159 drop_connection(context,
false,
false);
1160 ++m_sync_bad_spans_downloaded;
1163 previous = block_hash;
1165 if (start_height + i != this_height)
1168 drop_connection(context,
false,
false);
1169 ++m_sync_bad_spans_downloaded;
1173 auto req_it = context.m_requested_objects.find(block_hash);
1174 if(req_it == context.m_requested_objects.end())
1177 <<
" wasn't requested, dropping connection");
1178 drop_connection(context,
false,
false);
1179 ++m_sync_bad_spans_downloaded;
1182 if(
b.
tx_hashes.size() != arg.blocks[i].txs.size())
1185 <<
", tx_hashes.size()=" <<
b.
tx_hashes.size() <<
" mismatch with block_complete_entry.m_txs.size()=" << arg.blocks[i].txs.size() <<
", dropping connection");
1186 drop_connection(context,
false,
false);
1187 ++m_sync_bad_spans_downloaded;
1191 context.m_requested_objects.erase(req_it);
1192 block_hashes.push_back(block_hash);
1195 if(!context.m_requested_objects.empty())
1197 MERROR(context <<
"returned not all requested objects (context.m_requested_objects.size()="
1198 << context.m_requested_objects.size() <<
"), dropping connection");
1199 drop_connection(context,
false,
false);
1200 ++m_sync_bad_spans_downloaded;
1204 const bool pruned_ok = should_ask_for_pruned_data(context, start_height, arg.blocks.size(),
true);
1210 if (block_entry.pruned)
1212 MERROR(context <<
"returned a pruned block, dropping connection");
1213 drop_connection(context,
false,
false);
1214 ++m_sync_bad_spans_downloaded;
1217 if (block_entry.block_weight)
1219 MERROR(context <<
"returned a block weight for a non pruned block, dropping connection");
1220 drop_connection(context,
false,
false);
1221 ++m_sync_bad_spans_downloaded;
1228 MERROR(context <<
"returned at least one pruned object which we did not expect, dropping connection");
1229 drop_connection(context,
false,
false);
1230 ++m_sync_bad_spans_downloaded;
1241 if (block_entry.block_weight == 0 && block_entry.pruned)
1243 MERROR(context <<
"returned at least one pruned block with 0 weight, dropping connection");
1244 drop_connection(context,
false,
false);
1245 ++m_sync_bad_spans_downloaded;
1252 MLOG_YELLOW(
el::Level::Debug, context <<
" Got NEW BLOCKS inside of " << __FUNCTION__ <<
": size: " << arg.blocks.size()
1253 <<
", blocks: " << start_height <<
" - " << (start_height + arg.blocks.size() - 1) <<
1257 const boost::posix_time::time_duration dt = now - request_time;
1258 const float rate = size * 1e6 / (dt.total_microseconds() + 1);
1259 MDEBUG(context <<
" adding span: " << arg.blocks.size() <<
" at height " << start_height <<
", " << dt.total_microseconds()/1e6 <<
" seconds, " << (rate/1024) <<
" kB/s, size now " << (m_block_queue.get_data_size() + blocks_size) / 1048576.f <<
" MB");
1260 m_block_queue.add_blocks(start_height, arg.blocks, context.m_connection_id, context.m_remote_address, rate, blocks_size);
1263 context.m_last_known_hash = last_block_hash;
1265 if (!m_core.get_test_drop_download() || !m_core.get_test_drop_download_height()) {
1270 try_add_next_blocks(context);
1275 template<
class t_core>
1285 if (target_blockchain_height <= current_blockchain_height)
1291 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
1292 const boost::posix_time::time_duration sync_time = now - m_sync_start_time;
1298 float us_per_weight = (float)sync_time.total_microseconds() / (float)synced_weight;
1300 float remaining_us = us_per_weight * (float)remaining_weight;
1301 return (uint64_t)(remaining_us / 1e6);
1305 template<
class t_core>
1308 std::string
text =
"";
1309 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
1310 boost::posix_time::time_duration period_sync_time = now - m_period_start_time;
1311 if (period_sync_time > boost::posix_time::minutes(2))
1314 uint64_t remaining_seconds = get_estimated_remaining_sync_seconds(current_blockchain_height, target_blockchain_height);
1318 m_period_start_time = now;
1323 template<
class t_core>
1326 bool force_next_span =
false;
1332 const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock};
1333 if (!sync.owns_lock())
1335 MINFO(context <<
"Failed to lock m_sync_lock, going back to download");
1338 MDEBUG(context <<
" lock m_sync_lock, adding blocks to chain...");
1342 m_core.pause_mine();
1343 m_add_timer.resume();
1344 bool starting =
true;
1346 m_add_timer.pause();
1347 m_core.resume_mine();
1351 m_sync_start_time = boost::posix_time::microsec_clock::universal_time();
1352 m_sync_start_height = m_core.get_current_blockchain_height();
1353 m_period_start_time = m_sync_start_time;
1357 const uint64_t previous_height = m_core.get_current_blockchain_height();
1358 uint64_t start_height;
1359 std::vector<cryptonote::block_complete_entry>
blocks;
1360 boost::uuids::uuid span_connection_id;
1362 if (!m_block_queue.get_next_span(start_height,
blocks, span_connection_id, span_origin))
1364 MDEBUG(context <<
" no next span found, going back to download");
1370 MERROR(context <<
"Next span has no blocks");
1371 m_block_queue.remove_spans(span_connection_id, start_height);
1375 MDEBUG(context <<
" next span in the queue has blocks " << start_height <<
"-" << (start_height +
blocks.size() - 1)
1376 <<
", we need " << previous_height);
1382 MERROR(context <<
"Failed to parse block, but it should already have been parsed");
1383 m_block_queue.remove_spans(span_connection_id, start_height);
1386 if (m_core.have_block(last_block_hash))
1388 const uint64_t subchain_height = start_height +
blocks.size();
1389 LOG_DEBUG_CC(context,
"These are old blocks, ignoring: blocks " << start_height <<
" - " << (subchain_height-1) <<
", blockchain height " << m_core.get_current_blockchain_height());
1390 m_block_queue.remove_spans(span_connection_id, start_height);
1391 ++m_sync_old_spans_downloaded;
1396 MERROR(context <<
"Failed to parse block, but it should already have been parsed");
1397 m_block_queue.remove_spans(span_connection_id, start_height);
1400 bool parent_known = m_core.have_block(new_block.
prev_id);
1403 const std::uint64_t confirmed_height = m_block_queue.have_height(new_block.
prev_id);
1404 if (confirmed_height != std::numeric_limits<std::uint64_t>::max() && confirmed_height + 1 != start_height)
1406 MERROR(context <<
"Found incorrect height for " << new_block.
prev_id <<
" provided by " << span_connection_id);
1407 drop_connection(span_connection_id);
1416 bool parent_requested = m_block_queue.requested(new_block.
prev_id);
1417 if (!parent_requested)
1422 if (start_height > previous_height)
1424 if (should_drop_connection(context, get_next_needed_pruning_stripe().first))
1426 MDEBUG(context <<
"Got block with unknown parent which was not requested, but peer does not have that block - dropping connection");
1427 if (!context.m_is_income)
1428 m_p2p->add_used_stripe_peer(context);
1429 drop_connection(context,
false,
true);
1432 MDEBUG(context <<
"Got block with unknown parent which was not requested, but peer does not have that block - back to download");
1439 LOG_ERROR_CCONTEXT(
"Got block with unknown parent which was not requested - querying block hashes");
1440 m_block_queue.remove_spans(span_connection_id, start_height);
1441 context.m_needed_objects.clear();
1442 context.m_last_response_height = 0;
1447 MINFO(context <<
" parent was requested, we'll get back to it");
1451 const boost::posix_time::ptime
start = boost::posix_time::microsec_clock::universal_time();
1456 if (m_last_add_end_time)
1460 MINFO(
"Restarting adding block after idle for " << ns/1e9 <<
" seconds");
1464 std::vector<block> pblocks;
1465 if (!m_core.prepare_handle_incoming_blocks(
blocks, pblocks))
1468 drop_connections(span_origin);
1471 if (!pblocks.empty() && pblocks.size() !=
blocks.size())
1473 m_core.cleanup_handle_incoming_blocks();
1478 uint64_t block_process_time_full = 0, transactions_process_time_full = 0;
1479 size_t num_txs = 0, blockidx = 0;
1484 m_core.cleanup_handle_incoming_blocks();
1490 num_txs += block_entry.txs.size();
1495 drop_connections(span_origin);
1497 LOG_ERROR_CCONTEXT(
"transaction parsing failed for 1 or more txs in NOTIFY_RESPONSE_GET_OBJECTS,"
1498 "dropping connections");
1499 drop_connection(context, false, true);
1504 if (!m_core.cleanup_handle_incoming_blocks())
1510 m_block_queue.remove_spans(span_connection_id, start_height);
1514 transactions_process_time_full += transactions_process_time;
1521 m_core.handle_incoming_block(block_entry.block,
1522 pblocks.empty() ? NULL : &pblocks[blockidx],
1529 drop_connections(span_origin);
1531 LOG_PRINT_CCONTEXT_L1(
"Block verification failed, dropping connection");
1532 drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, true);
1537 if (!m_core.cleanup_handle_incoming_blocks())
1544 m_block_queue.remove_spans(span_connection_id, start_height);
1549 drop_connections(span_origin);
1551 LOG_PRINT_CCONTEXT_L1(
"Block received at sync phase was marked as orphaned, dropping connection");
1552 drop_connection(context, true, true);
1557 if (!m_core.cleanup_handle_incoming_blocks())
1564 m_block_queue.remove_spans(span_connection_id, start_height);
1569 block_process_time_full += block_process_time;
1574 MDEBUG(context <<
"Block process time (" <<
blocks.size() <<
" blocks, " << num_txs <<
" txs): " << block_process_time_full + transactions_process_time_full <<
" (" << transactions_process_time_full <<
"/" << block_process_time_full <<
") ms");
1576 if (!m_core.cleanup_handle_incoming_blocks())
1582 m_block_queue.remove_spans(span_connection_id, start_height);
1584 const uint64_t current_blockchain_height = m_core.get_current_blockchain_height();
1585 if (current_blockchain_height > previous_height)
1587 const uint64_t target_blockchain_height = m_core.get_target_blockchain_height();
1588 const boost::posix_time::time_duration dt = boost::posix_time::microsec_clock::universal_time() -
start;
1589 std::string progress_message =
"";
1590 if (current_blockchain_height < target_blockchain_height)
1592 uint64_t completion_percent = (current_blockchain_height * 100 / target_blockchain_height);
1593 if (completion_percent == 100)
1594 completion_percent = 99;
1595 progress_message =
" (" + std::to_string(completion_percent) +
"%, "
1596 + std::to_string(target_blockchain_height - current_blockchain_height) +
" left";
1597 std::string time_message = get_periodic_sync_estimate(current_blockchain_height, target_blockchain_height);
1598 if (!time_message.empty())
1600 uint64_t total_blocks_to_sync = target_blockchain_height - m_sync_start_height;
1601 uint64_t total_blocks_synced = current_blockchain_height - m_sync_start_height;
1602 progress_message +=
", " + std::to_string(total_blocks_synced * 100 / total_blocks_to_sync) +
"% of total synced";
1603 progress_message +=
", estimated " + time_message +
" left";
1605 progress_message +=
")";
1609 std::string timing_message =
"";
1611 timing_message = std::string(
" (") + std::to_string(dt.total_microseconds()/1e6) +
" sec, "
1612 + std::to_string((current_blockchain_height - previous_height) * 1e6 / dt.total_microseconds())
1613 +
" blocks/sec), " + std::to_string(m_block_queue.get_data_size() / 1048576.f) +
" MB queued in "
1614 + std::to_string(m_block_queue.get_num_filled_spans()) +
" spans, stripe "
1615 + std::to_string(previous_stripe) +
" -> " + std::to_string(current_stripe);
1617 timing_message += std::string(
": ") + m_block_queue.get_overview(current_blockchain_height);
1618 MGINFO_YELLOW(
"Synced " << current_blockchain_height <<
"/" << target_blockchain_height
1619 << progress_message << timing_message);
1620 if (previous_stripe != current_stripe)
1621 notify_new_stripe(context, current_stripe);
1628 if (should_download_next_span(context,
false))
1630 force_next_span =
true;
1632 else if (should_drop_connection(context, get_next_needed_pruning_stripe().first))
1634 if (!context.m_is_income)
1636 m_p2p->add_used_stripe_peer(context);
1637 drop_connection(context,
false,
false);
1644 if (!request_missing_objects(context,
true, force_next_span))
1647 drop_connection(context,
false,
false);
1653 template<
class t_core>
1663 if (stripe && peer_stripe && peer_stripe != stripe)
1665 context.m_new_stripe_notification =
true;
1667 ++context.m_callback_request_count;
1668 m_p2p->request_callback(context);
1675 template<
class t_core>
1681 return m_core.on_idle();
1684 template<
class t_core>
1687 MTRACE(
"Checking for idle peers...");
1692 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
1693 const boost::posix_time::time_duration dt = now - context.m_last_request_time;
1694 const auto ms = dt.total_microseconds();
1695 if (ms > IDLE_PEER_KICK_TIME || (context.m_expect_response && ms > NON_RESPONSIVE_PEER_KICK_TIME))
1697 context.m_idle_peer_notification = true;
1698 LOG_PRINT_CCONTEXT_L2(
"requesting callback");
1699 ++context.m_callback_request_count;
1700 m_p2p->request_callback(context);
1701 MLOG_PEER_STATE(
"requesting callback");
1710 template<
class t_core>
1713 const uint64_t target = m_core.get_target_blockchain_height();
1714 const uint64_t height = m_core.get_current_blockchain_height();
1715 if (target > height)
1718 MTRACE(
"Checking for outgoing syncing peers...");
1719 std::unordered_map<epee::net_utils::zone, unsigned> n_syncing, n_synced;
1720 std::unordered_map<epee::net_utils::zone, boost::uuids::uuid> last_synced_peer_id;
1721 std::vector<epee::net_utils::zone> zones;
1724 if (!peer_id || context.m_is_income)
1728 if (n_syncing.find(zone) == n_syncing.end())
1730 n_syncing[zone] = 0;
1732 last_synced_peer_id[zone] = boost::uuids::nil_uuid();
1733 zones.push_back(zone);
1736 if (context.m_state == cryptonote_connection_context::state_synchronizing)
1738 if (context.m_state == cryptonote_connection_context::state_normal)
1741 if (!context.m_anchor)
1742 last_synced_peer_id[zone] = context.m_connection_id;
1747 for (
const auto& zone : zones)
1749 const unsigned int max_out_peers = get_max_out_peers(zone);
1750 MTRACE(
"[" <<
epee::net_utils::zone_to_string(zone) <<
"] " << n_syncing[zone] <<
" syncing, " << n_synced[zone] <<
" synced, " << max_out_peers <<
" max out peers");
1756 MINFO(ctx <<
"dropping synced peer, " << n_syncing[zone] <<
" syncing, " << n_synced[zone] <<
" synced, " << max_out_peers <<
" max out peers");
1757 drop_connection(ctx, false, false);
1760 MDEBUG(
"Failed to find peer we wanted to drop");
1767 template<
class t_core>
1772 if (context.m_state == cryptonote_connection_context::state_standby)
1774 LOG_PRINT_CCONTEXT_L2(
"requesting callback");
1775 ++context.m_callback_request_count;
1776 m_p2p->request_callback(context);
1783 template<
class t_core>
1786 MLOG_P2P_MESSAGE(
"Received NOTIFY_REQUEST_CHAIN (" << arg.block_ids.size() <<
" blocks");
1787 if (context.m_state == cryptonote_connection_context::state_before_handshake)
1790 drop_connection(context,
false,
false);
1794 if(!m_core.find_blockchain_supplement(arg.block_ids, !arg.prune, r))
1799 if (r.m_block_ids.size() >= 2)
1802 if (!m_core.get_block_by_hash(r.m_block_ids[1],
b))
1809 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());
1810 post_notify<NOTIFY_RESPONSE_CHAIN_ENTRY>(r, context);
1814 template<
class t_core>
1817 std::vector<crypto::hash>
hashes;
1818 boost::posix_time::ptime request_time;
1819 boost::uuids::uuid connection_id;
1822 const uint64_t blockchain_height = m_core.get_current_blockchain_height();
1823 if (context.m_remote_blockchain_height <= blockchain_height)
1825 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
1826 const bool has_next_block =
tools::has_unpruned_block(blockchain_height, context.m_remote_blockchain_height, context.m_pruning_seed);
1829 if (!m_block_queue.has_next_span(blockchain_height, filled, request_time, connection_id))
1831 MDEBUG(context <<
" we should download it as no peer reserved it");
1836 const long dt = (now - request_time).total_microseconds();
1839 MDEBUG(context <<
" we should download it as it's not been received yet after " << dt/1e6);
1845 const double dl_speed = context.m_max_speed_down;
1848 bool download =
false;
1850 const time_t nowt = time(NULL);
1851 const time_t time_since_last_recv = nowt - ctx.m_last_recv;
1852 const float last_activity = std::min((float)time_since_last_recv, dt/1e6f);
1853 const bool stalled = last_activity > LAST_ACTIVITY_STALL_THRESHOLD;
1856 MDEBUG(context <<
" we should download it as the downloading peer is stalling for " << nowt - ctx.m_last_recv <<
" seconds");
1866 const float max_multiplier = 10.f;
1867 const float min_multiplier = 1.25f;
1868 float multiplier = max_multiplier;
1872 multiplier = std::min(max_multiplier, std::max(min_multiplier, multiplier));
1876 MDEBUG(context <<
" we should download it as we are substantially faster (" << dl_speed <<
" vs "
1877 << ctx.
m_current_speed_down <<
", multiplier " << multiplier <<
" after " << dt/1e6 <<
" seconds)");
1889 MWARNING(context <<
" we should download it as the downloading peer is unexpectedly not known to us");
1899 template<
class t_core>
1902 if (context.m_anchor)
1904 MDEBUG(context <<
"This is an anchor peer, not dropping");
1907 if (context.m_pruning_seed == 0)
1909 MDEBUG(context <<
"This peer is not striped, not dropping");
1914 if (next_stripe == peer_stripe)
1916 MDEBUG(context <<
"This peer has needed stripe " << peer_stripe <<
", not dropping");
1920 if (m_sync_pruned_blocks && local_stripe && next_stripe != local_stripe)
1922 MDEBUG(context <<
"We can sync pruned blocks off this peer, not dropping");
1926 if (!context.m_needed_objects.empty())
1928 const uint64_t next_available_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
1931 MDEBUG(context <<
"This peer has unpruned next block at height " << next_available_block_height <<
", not dropping");
1936 if (next_stripe > 0)
1938 unsigned int n_out_peers = 0, n_peers_on_next_stripe = 0;
1943 ++n_peers_on_next_stripe;
1949 if ((n_out_peers >= max_out_peers && n_peers_on_next_stripe == 0) || (distance > 1 && n_peers_on_next_stripe <= 2) || distance > 2)
1951 MDEBUG(context <<
"we want seed " << next_stripe <<
", and either " << n_out_peers <<
" is at max out peers ("
1952 << max_out_peers <<
") or distance " << distance <<
" from " << next_stripe <<
" to " << peer_stripe <<
1953 " is too large and we have only " << n_peers_on_next_stripe <<
" peers on next seed, dropping connection to make space");
1957 MDEBUG(context <<
"End of checks, not dropping");
1961 template<
class t_core>
1966 while (skip < context.m_needed_objects.size() && (m_core.have_block(context.m_needed_objects[skip].first) || (check_block_queue && m_block_queue.have(context.m_needed_objects[skip].first))))
1970 if (skip + 1 == context.m_needed_objects.size())
1971 context.m_last_known_hash = context.m_needed_objects[skip].first;
1976 MDEBUG(context <<
"skipping " << skip <<
"/" << context.m_needed_objects.size() <<
" blocks");
1977 context.m_needed_objects = std::vector<std::pair<crypto::hash, uint64_t>>(context.m_needed_objects.begin() + skip, context.m_needed_objects.end());
1982 template<
class t_core>
1985 if (!m_sync_pruned_blocks)
1987 if (!m_core.is_within_compiled_block_hash_area(first_block_height + nblocks - 1))
1990 if (local_stripe == 0)
1993 static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(
HF_VERSION_SMALLER_BP + 1);
1994 if (first_block_height < bp_fork_height)
1999 if (full_data_needed)
2001 if (check_block_weights && !m_core.has_block_weights(first_block_height, nblocks))
2006 template<
class t_core>
2010 std::set<boost::uuids::uuid> live_connections;
2012 live_connections.insert(context.m_connection_id);
2015 m_block_queue.flush_stale_spans(live_connections);
2018 if (!force_next_span)
2022 size_t nspans = m_block_queue.get_num_filled_spans();
2023 size_t size = m_block_queue.get_data_size();
2024 const uint64_t bc_height = m_core.get_current_blockchain_height();
2025 const auto next_needed_pruning_stripe = get_next_needed_pruning_stripe();
2029 const size_t block_queue_size_threshold = m_block_download_max_size ? m_block_download_max_size :
BLOCK_QUEUE_SIZE_THRESHOLD;
2032 if (skip_unneeded_hashes(context,
true) && context.m_needed_objects.empty() && context.m_num_requested == 0)
2034 if (context.m_remote_blockchain_height > m_block_queue.get_next_needed_height(bc_height))
2036 MERROR(context <<
"Nothing we can request from this peer, and we did not request anything previously");
2039 MDEBUG(context <<
"Nothing to get from this peer, and it's not ahead of us, all done");
2040 context.set_state_normal();
2041 if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height())
2042 on_connection_synchronized();
2045 uint64_t next_needed_height = m_block_queue.get_next_needed_height(bc_height);
2046 uint64_t next_block_height;
2047 if (context.m_needed_objects.empty())
2048 next_block_height = next_needed_height;
2050 next_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
2052 bool stripe_proceed_secondary =
tools::has_unpruned_block(next_block_height, context.m_remote_blockchain_height, context.m_pruning_seed);
2053 bool proceed = stripe_proceed_main || (queue_proceed && stripe_proceed_secondary);
2056 if (!context.m_is_income)
2057 m_p2p->add_used_stripe_peer(context);
2061 MDEBUG(context <<
"proceed " << proceed <<
" (queue " << queue_proceed <<
", stripe " << stripe_proceed_main <<
"/" <<
2062 stripe_proceed_secondary <<
"), " << next_needed_pruning_stripe.first <<
"-" << next_needed_pruning_stripe.second <<
2063 " needed, bc add stripe " << add_stripe <<
", we have " << peer_stripe <<
"), bc_height " << bc_height);
2065 ", next_needed_height "<< next_needed_height);
2066 MDEBUG(context <<
" - last_response_height " << context.m_last_response_height <<
", m_needed_objects size " << context.m_needed_objects.size());
2070 if (stripe_proceed_main && should_download_next_span(context,
true))
2072 MDEBUG(context <<
" we should try for that next span too, we think we could get it faster, resuming");
2073 force_next_span =
true;
2080 if (context.m_state != cryptonote_connection_context::state_standby)
2082 LOG_DEBUG_CC(context,
"Block queue is " << nspans <<
" and " << size <<
", resuming");
2090 boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock};
2091 if (sync.owns_lock())
2093 bool filled =
false;
2094 boost::posix_time::ptime time;
2095 boost::uuids::uuid connection_id;
2096 if (m_block_queue.has_next_span(m_core.get_current_blockchain_height(), filled, time, connection_id) && filled)
2098 LOG_DEBUG_CC(context,
"No other thread is adding blocks, and next span needed is ready, resuming");
2100 context.m_state = cryptonote_connection_context::state_standby;
2101 ++context.m_callback_request_count;
2102 m_p2p->request_callback(context);
2110 if (!context.m_is_income)
2113 const uint64_t dt = now - m_last_add_end_time;
2116 MDEBUG(context <<
"ns " <<
tools::ticks_to_ns(dt) <<
" from " << m_last_add_end_time <<
" and " << now);
2117 MDEBUG(context <<
"Block addition seems to have wedged, dropping connection");
2124 if (context.m_state != cryptonote_connection_context::state_standby)
2127 LOG_DEBUG_CC(context,
"Block queue is " << nspans <<
" and " << size <<
", pausing");
2128 else if (!stripe_proceed_main && !stripe_proceed_secondary)
2129 LOG_DEBUG_CC(context,
"We do not have the stripe required to download another block, pausing");
2130 context.m_state = cryptonote_connection_context::state_standby;
2136 context.m_state = cryptonote_connection_context::state_synchronizing;
2139 MDEBUG(context <<
" request_missing_objects: check " << check_having_blocks <<
", force_next_span " << force_next_span
2140 <<
", m_needed_objects " << context.m_needed_objects.size() <<
" lrh " << context.m_last_response_height <<
", chain "
2142 if(context.m_needed_objects.size() || force_next_span)
2146 bool is_next =
false;
2148 const size_t count_limit = m_core.get_block_sync_size(m_core.get_current_blockchain_height());
2149 std::pair<uint64_t, uint64_t> span = std::make_pair(0, 0);
2150 if (force_next_span)
2152 if (span.second == 0)
2154 std::vector<crypto::hash>
hashes;
2155 boost::uuids::uuid span_connection_id;
2156 boost::posix_time::ptime time;
2157 span = m_block_queue.get_next_span_if_scheduled(
hashes, span_connection_id, time);
2158 if (span.second > 0)
2161 req.blocks.reserve(
hashes.size());
2162 for (
const auto &hash:
hashes)
2164 req.blocks.push_back(hash);
2165 context.m_requested_objects.insert(hash);
2167 m_block_queue.reset_next_span_time();
2171 if (span.second == 0)
2173 MDEBUG(context <<
" span size is 0");
2174 if (context.m_last_response_height + 1 < context.m_needed_objects.size())
2176 MERROR(context <<
" ERROR: inconsistent context: lrh " << context.m_last_response_height <<
", nos " << context.m_needed_objects.size());
2177 context.m_needed_objects.clear();
2178 context.m_last_response_height = 0;
2181 if (skip_unneeded_hashes(context,
false) && context.m_needed_objects.empty() && context.m_num_requested == 0)
2183 if (context.m_remote_blockchain_height > m_block_queue.get_next_needed_height(m_core.get_current_blockchain_height()))
2185 MERROR(context <<
"Nothing we can request from this peer, and we did not request anything previously");
2188 MDEBUG(context <<
"Nothing to get from this peer, and it's not ahead of us, all done");
2189 context.set_state_normal();
2190 if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height())
2191 on_connection_synchronized();
2195 const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
2196 static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
2197 bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
2198 span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
2199 MDEBUG(context <<
" span from " << first_block_height <<
": " << span.first <<
"/" << span.second);
2200 if (span.second > 0)
2205 MDEBUG(context <<
" starting early on next seed (" << span.first <<
" with stripe " << stripe <<
2210 if (span.second == 0 && !force_next_span)
2212 MDEBUG(context <<
" still no span reserved, we may be in the corner case of next span scheduled and everything else scheduled/filled");
2213 std::vector<crypto::hash>
hashes;
2214 boost::uuids::uuid span_connection_id;
2215 boost::posix_time::ptime time;
2216 span = m_block_queue.get_next_span_if_scheduled(
hashes, span_connection_id, time);
2217 if (span.second > 0 && !
tools::has_unpruned_block(span.first, context.m_remote_blockchain_height, context.m_pruning_seed))
2218 span = std::make_pair(0, 0);
2219 if (span.second > 0)
2222 req.blocks.reserve(
hashes.size());
2223 for (
const auto &hash:
hashes)
2225 req.blocks.push_back(hash);
2227 context.m_requested_objects.insert(hash);
2229 auto i = std::find_if(context.m_needed_objects.begin(), context.m_needed_objects.end(),
2230 [&hash](
const std::pair<crypto::hash, uint64_t> &o) { return o.first == hash; });
2231 if (i != context.m_needed_objects.end())
2232 context.m_needed_objects.erase(i);
2236 MDEBUG(context <<
" span: " << span.first <<
"/" << span.second <<
" (" << span.first <<
" - " << (span.first + span.second - 1) <<
")");
2237 if (span.second > 0)
2241 const uint64_t first_context_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
2242 uint64_t skip = span.first - first_context_block_height;
2243 if (skip > context.m_needed_objects.size())
2245 MERROR(
"ERROR: skip " << skip <<
", m_needed_objects " << context.m_needed_objects.size() <<
", first_context_block_height" << first_context_block_height);
2249 context.m_needed_objects = std::vector<std::pair<crypto::hash, uint64_t>>(context.m_needed_objects.begin() + skip, context.m_needed_objects.end());
2250 if (context.m_needed_objects.size() < span.second)
2252 MERROR(
"ERROR: span " << span.first <<
"/" << span.second <<
", m_needed_objects " << context.m_needed_objects.size());
2256 req.blocks.reserve(req.blocks.size() + span.second);
2257 for (
size_t n = 0; n < span.second; ++n)
2259 req.blocks.push_back(context.m_needed_objects[n].first);
2261 context.m_requested_objects.insert(context.m_needed_objects[n].first);
2263 context.m_needed_objects = std::vector<std::pair<crypto::hash, uint64_t>>(context.m_needed_objects.begin() + span.second, context.m_needed_objects.end());
2266 req.prune = should_ask_for_pruned_data(context, span.first, span.second,
true);
2269 if (!req.prune && context.m_pruning_seed)
2274 if (((first_stripe && peer_stripe != first_stripe) || (last_stripe && peer_stripe != last_stripe)) && !m_sync_pruned_blocks)
2276 MDEBUG(context <<
"We need full data, but the peer does not have it, dropping peer");
2280 context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
2281 context.m_expect_height = span.first;
2282 context.m_expect_response = NOTIFY_RESPONSE_GET_OBJECTS::ID;
2283 MLOG_P2P_MESSAGE(
"-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size()
2284 <<
"requested blocks count=" <<
count <<
" / " << count_limit <<
" from " << span.first <<
", first hash " << req.blocks.front());
2287 MDEBUG(
"Asking for " << (req.prune ?
"pruned" :
"full") <<
" data, start/end "
2292 context.m_num_requested += req.blocks.size();
2293 post_notify<NOTIFY_REQUEST_GET_OBJECTS>(req, context);
2299 const uint64_t blockchain_height = m_core.get_current_blockchain_height();
2300 if (std::max(blockchain_height, m_block_queue.get_next_needed_height(blockchain_height)) >= m_core.get_target_blockchain_height())
2302 context.set_state_normal();
2311 context.m_needed_objects.clear();
2316 if (m_core.get_current_blockchain_height() < m_core.get_target_blockchain_height())
2318 const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock};
2319 if (sync.owns_lock())
2321 uint64_t start_height;
2322 std::vector<cryptonote::block_complete_entry>
blocks;
2323 boost::uuids::uuid span_connection_id;
2325 if (m_block_queue.get_next_span(start_height,
blocks, span_connection_id, span_origin,
true))
2327 LOG_DEBUG_CC(context,
"No other thread is adding blocks, resuming");
2329 context.m_state = cryptonote_connection_context::state_standby;
2330 ++context.m_callback_request_count;
2331 m_p2p->request_callback(context);
2337 if(context.m_last_response_height < context.m_remote_blockchain_height-1)
2341 m_core.get_short_chain_history(r.block_ids, context.m_expect_height);
2342 CHECK_AND_ASSERT_MES(!r.block_ids.empty(),
false,
"Short chain history is empty");
2345 if (context.m_last_known_hash !=
crypto::null_hash && r.block_ids.front() != context.m_last_known_hash)
2347 context.m_expect_height = std::numeric_limits<uint64_t>::max();
2348 r.block_ids.push_front(context.m_last_known_hash);
2351 handler_request_blocks_history( r.block_ids );
2352 r.prune = m_sync_pruned_blocks;
2359 context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
2360 context.m_expect_response = NOTIFY_RESPONSE_CHAIN_ENTRY::ID;
2361 MLOG_P2P_MESSAGE(
"-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size());
2362 post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
2366 CHECK_AND_ASSERT_MES(context.m_last_response_height == context.m_remote_blockchain_height-1
2367 && !context.m_needed_objects.size()
2368 && !context.m_requested_objects.size(),
false,
"request_missing_blocks final condition failed!"
2369 <<
"\r\nm_last_response_height=" << context.m_last_response_height
2370 <<
"\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height
2371 <<
"\r\nm_needed_objects.size()=" << context.m_needed_objects.size()
2372 <<
"\r\nm_requested_objects.size()=" << context.m_requested_objects.size()
2375 context.set_state_normal();
2376 if (context.m_remote_blockchain_height >= m_core.get_target_blockchain_height())
2378 if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height())
2379 on_connection_synchronized();
2383 MINFO(context <<
" we've reached this peer's blockchain height (theirs " << context.m_remote_blockchain_height <<
", our target " << m_core.get_target_blockchain_height());
2389 template<
class t_core>
2392 bool val_expected =
false;
2393 uint64_t current_blockchain_height = m_core.get_current_blockchain_height();
2394 if(!m_core.is_within_compiled_block_hash_area(current_blockchain_height) && m_synchronized.compare_exchange_strong(val_expected,
true))
2396 if ((current_blockchain_height > m_sync_start_height) && (m_sync_spans_downloaded > 0))
2398 uint64_t synced_blocks = current_blockchain_height - m_sync_start_height;
2400 if (synced_blocks > 20)
2402 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
2403 uint64_t synced_seconds = (now - m_sync_start_time).total_seconds();
2404 if (synced_seconds == 0)
2408 float blocks_per_second = (1000 * synced_blocks / synced_seconds) / 1000.0f;
2409 MGINFO_YELLOW(
"Synced " << synced_blocks <<
" blocks in "
2413 MGINFO_YELLOW(ENDL <<
"**********************************************************************" << ENDL
2414 <<
"You are now synchronized with the network. You may now start monero-wallet-cli." << ENDL
2416 <<
"Use the \"help\" command to see the list of available commands." << ENDL
2417 <<
"**********************************************************************");
2418 m_sync_timer.pause();
2421 const uint64_t sync_time = m_sync_timer.value();
2422 const uint64_t add_time = m_add_timer.value();
2423 if (sync_time && add_time)
2425 MCLOG_YELLOW(
el::Level::Info,
"sync-info",
"Sync time: " << sync_time/1e9/60 <<
" min, idle time " <<
2426 (100.f * (1.0f - add_time / (
float)sync_time)) <<
"%" <<
", " <<
2427 (10 * m_sync_download_objects_size / 1024 / 1024) / 10.f <<
" + " <<
2428 (10 * m_sync_download_chain_size / 1024 / 1024) / 10.f <<
" MB downloaded, " <<
2429 100.0f * m_sync_old_spans_downloaded / m_sync_spans_downloaded <<
"% old spans, " <<
2430 100.0f * m_sync_bad_spans_downloaded / m_sync_spans_downloaded <<
"% bad spans");
2433 m_core.on_synchronized();
2435 m_core.safesyncmode(
true);
2436 m_p2p->clear_used_stripe_peers();
2439 val_expected =
true;
2440 if (m_ask_for_txpool_complement.compare_exchange_strong(val_expected,
false))
2444 if(context.m_state < cryptonote_connection_context::state_synchronizing)
2446 MDEBUG(context <<
"not ready, ignoring");
2449 if (!request_txpool_complement(context))
2451 MERROR(context <<
"Failed to request txpool complement");
2461 template<
class t_core>
2466 if(context.m_state == cryptonote_connection_context::state_synchronizing)
2473 template<
class t_core>
2476 MLOG_P2P_MESSAGE(
"Received NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size()
2477 <<
", m_start_height=" << arg.start_height <<
", m_total_height=" << arg.total_height <<
", expect height=" << context.m_expect_height);
2480 if (context.m_expect_response != NOTIFY_RESPONSE_CHAIN_ENTRY::ID)
2482 LOG_ERROR_CCONTEXT(
"Got NOTIFY_RESPONSE_CHAIN_ENTRY out of the blue, dropping connection");
2483 drop_connection(context,
true,
false);
2486 context.m_expect_response = 0;
2487 if (arg.start_height + 1 > context.m_expect_height)
2489 LOG_ERROR_CCONTEXT(
"Got NOTIFY_RESPONSE_CHAIN_ENTRY past expected height, dropping connection");
2490 drop_connection(context,
true,
false);
2494 context.m_last_request_time = boost::date_time::not_a_date_time;
2496 m_sync_download_chain_size += arg.m_block_ids.size() *
sizeof(
crypto::hash);
2498 if(!arg.m_block_ids.size())
2501 drop_connection(context,
true,
false);
2504 if (arg.total_height < arg.m_block_ids.size() || arg.start_height > arg.total_height - arg.m_block_ids.size())
2507 drop_connection(context,
true,
false);
2510 if (!arg.m_block_weights.empty() && arg.m_block_weights.size() != arg.m_block_ids.size())
2513 drop_connection(context,
true,
false);
2516 MDEBUG(context <<
"first block hash " << arg.m_block_ids.front() <<
", last " << arg.m_block_ids.back());
2520 LOG_ERROR_CCONTEXT(
"sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with total_height=" << arg.total_height <<
" and block_ids=" << arg.m_block_ids.size());
2521 drop_connection(context,
false,
false);
2524 if (arg.total_height < context.m_remote_blockchain_height)
2526 MINFO(context <<
"Claims " << arg.total_height <<
", claimed " << context.m_remote_blockchain_height <<
" before");
2527 hit_score(context, 1);
2529 context.m_remote_blockchain_height = arg.total_height;
2530 context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1;
2531 if(context.m_last_response_height > context.m_remote_blockchain_height)
2533 LOG_ERROR_CCONTEXT(
"sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with m_total_height=" << arg.total_height
2534 <<
", m_start_height=" << arg.start_height
2535 <<
", m_block_ids.size()=" << arg.m_block_ids.size());
2536 drop_connection(context,
false,
false);
2540 uint64_t n_use_blocks = m_core.prevalidate_block_hashes(arg.start_height, arg.m_block_ids, arg.m_block_weights);
2544 drop_connection(context,
true,
false);
2548 context.m_expected_heights_start = arg.start_height;
2550 context.m_expected_heights.clear();
2551 context.m_expected_heights.reserve(arg.m_block_ids.size());
2552 context.m_needed_objects.clear();
2553 context.m_needed_objects.reserve(arg.m_block_ids.size());
2555 std::unordered_set<crypto::hash> blocks_found;
2556 bool expect_unknown =
false;
2557 for (
size_t i = 0; i < arg.m_block_ids.size(); ++i)
2559 if (!blocks_found.insert(arg.m_block_ids[i]).second)
2562 drop_connection_with_score(context, 5,
false);
2566 const bool have_block = m_core.have_block_unlocked(arg.m_block_ids[i], &where);
2570 if (!have_block && m_block_queue.have_height(arg.m_block_ids[i]) != arg.start_height)
2573 drop_connection_with_score(context, 5,
false);
2577 expect_unknown =
true;
2589 LOG_ERROR_CCONTEXT(
"Block is invalid or known without known type, dropping connection");
2590 drop_connection(context,
true,
false);
2595 LOG_ERROR_CCONTEXT(
"Block is on the main chain, but we did not expect a known block, dropping connection");
2596 drop_connection_with_score(context, 5,
false);
2599 if (m_core.get_block_id_by_height(arg.start_height + i) != arg.m_block_ids[i])
2601 LOG_ERROR_CCONTEXT(
"Block is on the main chain, but not at the expected height, dropping connection");
2602 drop_connection_with_score(context, 5,
false);
2609 LOG_ERROR_CCONTEXT(
"Block is on the main chain, but we did not expect a known block, dropping connection");
2610 drop_connection_with_score(context, 5,
false);
2617 expect_unknown =
true;
2619 const uint64_t
block_weight = arg.m_block_weights.empty() ? 0 : arg.m_block_weights[i];
2620 context.m_expected_heights.push_back(arg.m_block_ids[i]);
2621 context.m_needed_objects.push_back(std::make_pair(arg.m_block_ids[i],
block_weight));
2622 if (++added == n_use_blocks)
2625 context.m_last_response_height -= arg.m_block_ids.size() - n_use_blocks;
2627 if (!request_missing_objects(context,
false))
2630 drop_connection(context,
false,
false);
2634 if (arg.total_height > m_core.get_target_blockchain_height())
2635 m_core.set_target_blockchain_height(arg.total_height);
2637 context.m_num_requested = 0;
2641 template<
class t_core>
2645 std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> fluffyConnections;
2651 LOG_DEBUG_CC(context,
"RELAYING FLUFFY BLOCK TO PEER");
2652 fluffyConnections.push_back({context.m_remote_address.get_zone(), context.m_connection_id});
2658 if (!fluffyConnections.empty())
2662 m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, std::move(fluffyBlob), std::move(fluffyConnections));
2668 template<
class t_core>
2679 template<
class t_core>
2683 if (!m_core.get_pool_transaction_hashes(r.hashes,
false))
2685 MERROR(
"Failed to get txpool hashes");
2688 MLOG_P2P_MESSAGE(
"-->>NOTIFY_GET_TXPOOL_COMPLEMENT: hashes.size()=" << r.hashes.size() );
2689 post_notify<NOTIFY_GET_TXPOOL_COMPLEMENT>(r, context);
2694 template<
class t_core>
2699 MERROR(
"Negative score hit");
2702 context.m_score -= score;
2704 drop_connection_with_score(context, 5,
false);
2707 template<
class t_core>
2710 std::stringstream ss;
2711 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
2715 ss << stripe + state_char;
2724 template<
class t_core>
2727 const uint64_t want_height_from_blockchain = m_core.get_current_blockchain_height();
2728 const uint64_t want_height_from_block_queue = m_block_queue.get_next_needed_height(want_height_from_blockchain);
2729 const uint64_t want_height = std::max(want_height_from_blockchain, want_height_from_block_queue);
2730 uint64_t blockchain_height = m_core.get_target_blockchain_height();
2732 if (blockchain_height == 0)
2735 if (next_pruning_stripe == 0)
2736 return std::make_pair(0, 0);
2738 unsigned int n_next = 0, n_subsequent = 0, n_others = 0;
2741 if (context.m_state >= cryptonote_connection_context::state_synchronizing)
2754 const bool use_next = (n_next > max_out_peers / 2 && n_subsequent <= 1) || (n_next > 2 && n_subsequent == 0);
2755 const uint32_t ret_stripe = use_next ? subsequent_pruning_stripe: next_pruning_stripe;
2756 MIDEBUG(
const std::string po = get_peers_overview(),
"get_next_needed_pruning_stripe: want height " << want_height <<
" (" <<
2757 want_height_from_blockchain <<
" from blockchain, " << want_height_from_block_queue <<
" from block queue), stripe " <<
2758 next_pruning_stripe <<
" (" << n_next <<
"/" << max_out_peers <<
" on it and " << n_subsequent <<
" on " <<
2759 subsequent_pruning_stripe <<
", " << n_others <<
" others) -> " << ret_stripe <<
" (+" <<
2761 "), current peers " << po);
2762 return std::make_pair(next_pruning_stripe, ret_stripe);
2765 template<
class t_core>
2768 const uint64_t target = m_core.get_target_blockchain_height();
2769 const uint64_t height = m_core.get_current_blockchain_height();
2770 if (target && target <= height)
2772 size_t n_out_peers = 0;
2778 if (n_out_peers >= get_max_out_peers(zone))
2783 template<
class t_core>
2786 const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock};
2787 return !sync.owns_lock();
2790 template<
class t_core>
2793 LOG_DEBUG_CC(context,
"dropping connection id " << context.m_connection_id <<
" (pruning seed " <<
2795 "), score " << score <<
", flush_all_spans " << flush_all_spans);
2798 m_p2p->add_host_fail(context.m_remote_address, score);
2800 m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
2802 m_p2p->drop_connection(context);
2805 template<
class t_core>
2808 return drop_connection_with_score(context, add_fail ? 1 : 0, flush_all_spans);
2811 template<
class t_core>
2816 drop_connection(context,
true,
false);
2821 template<
class t_core>
2824 MWARNING(
"dropping connections to " <<
address.str());
2826 m_p2p->add_host_fail(
address, 5);
2828 std::vector<boost::uuids::uuid> drop;
2834 for (
const boost::uuids::uuid &
id: drop)
2836 m_block_queue.flush_spans(
id,
true);
2839 drop_connection(context,
true,
false);
2845 template<
class t_core>
2848 uint64_t target = 0;
2850 if (cntxt.
m_state >= cryptonote_connection_context::state_synchronizing && cntxt.
m_connection_id != context.m_connection_id)
2854 const uint64_t previous_target = m_core.get_target_blockchain_height();
2855 if (target < previous_target)
2857 MINFO(
"Target height decreasing from " << previous_target <<
" to " << target);
2858 m_core.set_target_blockchain_height(target);
2859 if (target == 0 && context.m_state > cryptonote_connection_context::state_before_handshake && !m_stopping)
2861 MCWARNING(
"global",
"monerod is now disconnected from the network");
2862 m_ask_for_txpool_complement =
true;
2866 m_block_queue.flush_spans(context.m_connection_id,
false);
2871 template<
class t_core>
cryptonote::block b
Definition block.cpp:40
Definition cryptonote_protocol_handler.h:80
uint64_t get_estimated_remaining_sync_seconds(uint64_t current_blockchain_height, uint64_t target_blockchain_height)
Definition cryptonote_protocol_handler.inl:1276
bool get_payload_sync_data(epee::byte_slice &data)
Definition cryptonote_protocol_handler.inl:558
t_cryptonote_protocol_handler(t_core &rcore, nodetool::i_p2p_endpoint< connection_context > *p_net_layout, bool offline=false)
Definition cryptonote_protocol_handler.inl:182
void set_p2p_endpoint(nodetool::i_p2p_endpoint< connection_context > *p2p)
Definition cryptonote_protocol_handler.inl:222
int handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:878
bool process_payload_sync_data(const CORE_SYNC_DATA &hshd, cryptonote_connection_context &context, bool is_inital)
Definition cryptonote_protocol_handler.inl:433
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe)
Definition cryptonote_protocol_handler.inl:1654
double get_avg_block_size()
Definition cryptonote_protocol_handler.inl:1013
std::string get_periodic_sync_estimate(uint64_t current_blockchain_height, uint64_t target_blockchain_height)
Definition cryptonote_protocol_handler.inl:1306
bool init(const boost::program_options::variables_map &vm)
Definition cryptonote_protocol_handler.inl:196
nodetool::i_p2p_endpoint< connection_context > * m_p2p
Definition cryptonote_protocol_handler.h:174
int handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:974
int try_add_next_blocks(cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:1324
bool kick_idle_peers()
Definition cryptonote_protocol_handler.inl:1685
bool on_idle()
Definition cryptonote_protocol_handler.inl:1676
int handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:581
bool on_callback(cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:231
std::list< connection_info > get_connections()
Definition cryptonote_protocol_handler.inl:361
int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:567
bool deinit()
Definition cryptonote_protocol_handler.inl:216
nodetool::p2p_endpoint_stub< connection_context > m_p2p_stub
Definition cryptonote_protocol_handler.h:173
int handle_notify_get_txpool_complement(int command, NOTIFY_GET_TXPOOL_COMPLEMENT::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:848
void stop()
Definition cryptonote_protocol_handler.inl:2872
int handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:1026
int handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request &arg, cryptonote_connection_context &context)
Definition cryptonote_protocol_handler.inl:750
void log_connections()
Definition cryptonote_protocol_handler.inl:296
std::vector< txin_v > vin
Definition cryptonote_basic.h:178
Definition cryptonote_basic.h:205
crypto::hash prunable_hash
Definition cryptonote_basic.h:218
Definition byte_slice.h:69
Provides space for levin (p2p) header, so that payload can be sent without copy.
Definition levin_base.h:132
Definition net_utils_base.h:69
static constexpr address_type get_type_id() noexcept
Definition net_utils_base.h:92
constexpr uint16_t port() const noexcept
Definition net_utils_base.h:87
Definition net_utils_base.h:225
bool is_loopback() const
Definition net_utils_base.h:314
std::string str() const
Definition net_utils_base.h:312
address_type get_type_id() const
Definition net_utils_base.h:316
bool is_local() const
Definition net_utils_base.h:315
std::string host_str() const
Definition net_utils_base.h:313
zone get_zone() const
Definition net_utils_base.h:317
const Type & as() const
Definition net_utils_base.h:320
#define DIFFICULTY_TARGET_V1
Definition cryptonote_config.h:81
#define HASH_OF_HASHES_STEP
Definition cryptonote_config.h:199
#define P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT
Definition cryptonote_config.h:151
#define HF_VERSION_SMALLER_BP
Definition cryptonote_config.h:181
#define CRYPTONOTE_PRUNING_LOG_STRIPES
Definition cryptonote_config.h:207
#define DIFFICULTY_TARGET_V2
Definition cryptonote_config.h:80
#define CRYPTONOTE_MAX_BLOCK_NUMBER
Definition cryptonote_config.h:40
#define P2P_IP_FAILS_BEFORE_BLOCK
Definition cryptonote_config.h:157
#define BLOCKS_IDS_SYNCHRONIZING_MAX_COUNT
Definition cryptonote_config.h:97
@ HAVE_BLOCK_MAIN_CHAIN
Definition cryptonote_core.h:57
@ HAVE_BLOCK_INVALID
Definition cryptonote_core.h:57
@ HAVE_BLOCK_ALT_CHAIN
Definition cryptonote_core.h:57
#define CURRENCY_PROTOCOL_MAX_OBJECT_REQUEST_COUNT
Definition cryptonote_protocol_handler.h:57
#define IDLE_PEER_KICK_TIME
Definition cryptonote_protocol_handler.inl:74
#define REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD_STANDBY
Definition cryptonote_protocol_handler.inl:72
#define DROP_ON_SYNC_WEDGE_THRESHOLD
Definition cryptonote_protocol_handler.inl:77
#define DROP_PEERS_ON_SCORE
Definition cryptonote_protocol_handler.inl:79
#define MLOG_PEER_STATE(x)
Definition cryptonote_protocol_handler.inl:66
#define MLOG_P2P_MESSAGE(x)
Definition cryptonote_protocol_handler.inl:52
#define REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD
Definition cryptonote_protocol_handler.inl:73
#define NON_RESPONSIVE_PEER_KICK_TIME
Definition cryptonote_protocol_handler.inl:75
#define MLOGIF_P2P_MESSAGE(init, test, x)
Definition cryptonote_protocol_handler.inl:53
#define BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS
Definition cryptonote_protocol_handler.inl:71
#define BLOCK_QUEUE_SIZE_THRESHOLD
Definition cryptonote_protocol_handler.inl:70
#define BLOCK_QUEUE_NSPANS_THRESHOLD
Definition cryptonote_protocol_handler.inl:69
#define ELPP
Definition easylogging++.h:2794
int * count
Definition gmock_stress_test.cc:176
relay_method tx_relay
Definition levin_notify.cpp:549
static int version
Definition mdb_load.c:29
const char * text
Definition minihttptestserver.c:269
uint32_t address
Definition getifaddr.c:269
Definition block_weight.py:1
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition command_line.h:269
static constexpr crypto::hash null_hash
Definition hash.h:102
POD_CLASS hash
Definition hash.h:49
Holds cryptonote related classes and helpers.
Definition blockchain_db.cpp:45
const command_line::arg_descriptor< bool > arg_sync_pruned_blocks
Definition cryptonote_core.cpp:126
boost::multiprecision::uint128_t difficulty_type
Definition difficulty.h:41
network_type
Definition cryptonote_config.h:302
@ TESTNET
Definition cryptonote_config.h:304
@ MAINNET
Definition cryptonote_config.h:303
relay_method
Methods tracking how a tx was received and relayed.
Definition enums.h:37
@ block
Received in block, takes precedence over others.
@ none
Received via RPC with do_not_relay set.
@ forward
Received over i2p/tor; timer delayed before ipv4/6 public broadcast.
@ fluff
Received/sent over network using Dandelion++ fluff.
@ stem
Received/send over network using Dandelion++ stem.
@ local
Received via RPC; trying to send over i2p/tor, etc.
bool get_block_hash(const block &b, crypto::hash &res)
Definition cryptonote_format_utils.cpp:1507
bool make_full_pool_supplement_from_block_entry(const cryptonote::block_complete_entry &blk_entry, cryptonote::pool_supplement &pool_supplement)
Definition cryptonote_protocol_handler.inl:145
bool parse_and_validate_tx_from_blob(const blobdata_ref &tx_blob, transaction &tx)
Definition cryptonote_format_utils.cpp:224
blobdata block_to_blob(const block &b)
Definition cryptonote_format_utils.cpp:1579
std::string get_protocol_state_string(cryptonote_connection_context::state s)
Definition connection_context.h:123
size_t get_max_tx_size()
Definition cryptonote_basic_impl.cpp:78
void get_blob_hash(const blobdata_ref &blob, crypto::hash &res)
Definition cryptonote_format_utils.cpp:1116
crypto::hash get_pruned_transaction_hash(const transaction &t, const crypto::hash &pruned_data_hash)
Definition cryptonote_format_utils.cpp:1329
bool make_pool_supplement_from_block_entry(const std::vector< cryptonote::tx_blob_entry > &tx_entries, const CryptoHashContainer &blk_tx_hashes, const bool allow_pruned, cryptonote::pool_supplement &pool_supplement)
Definition cryptonote_protocol_handler.inl:84
const command_line::arg_descriptor< size_t > arg_block_download_max_size
Definition cryptonote_core.cpp:121
char get_protocol_state_char(cryptonote_connection_context::state s)
Definition connection_context.h:142
bool parse_and_validate_tx_base_from_blob(const blobdata_ref &tx_blob, transaction &tx)
Definition cryptonote_format_utils.cpp:235
bool parse_and_validate_block_from_blob(const blobdata_ref &b_blob, block &b, crypto::hash *block_hash)
Definition cryptonote_format_utils.cpp:1553
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
Definition cryptonote_format_utils.h:165
@ Info
Mainly useful to represent current progress of application.
@ Debug
Informational events most useful for developers to debug application.
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
Definition misc_language.h:80
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
Definition misc_language.h:97
const char * zone_to_string(zone value) noexcept
Definition net_utils_base.cpp:135
zone
Definition enums.h:50
std::string print_connection_context_short(const connection_context_base &ctx)
Definition net_utils_base.cpp:128
bool store_t_to_binary(t_struct &str_in, byte_slice &binary_buff, size_t initial_buffer_size=8192)
Definition portable_storage_template_helper.h:118
#define LOG_ERROR_CCONTEXT(message)
Definition net_utils_base.h:486
#define LOG_DEBUG_CC(ct, message)
Definition net_utils_base.h:472
#define LOG_PRINT_CCONTEXT_L1(message)
Definition net_utils_base.h:483
#define LOG_PRINT_CCONTEXT_L0(message)
Definition net_utils_base.h:482
#define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message)
Definition net_utils_base.h:488
#define LOG_PRINT_CCONTEXT_L2(message)
Definition net_utils_base.h:484
implementaion for throttling of connection (count and rate-limit speed etc)
const CharType(& source)[N]
Definition pointer.h:1147
#define blocks
Definition sha512-hash.c:11
if(!cryptonote::get_account_address_from_str_or_url(info, cryptonote::TESTNET, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN"))
Definition signature.cpp:53
#define true
Definition stdbool.h:36
#define false
Definition stdbool.h:37
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
signed int int32_t
Definition stdint.h:123
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
Definition cryptonote_protocol_defs.h:251
uint64_t cumulative_difficulty_top64
Definition cryptonote_protocol_defs.h:254
uint32_t pruning_seed
Definition cryptonote_protocol_defs.h:257
uint64_t cumulative_difficulty
Definition cryptonote_protocol_defs.h:253
uint8_t top_version
Definition cryptonote_protocol_defs.h:256
uint64_t current_height
Definition cryptonote_protocol_defs.h:252
crypto::hash top_id
Definition cryptonote_protocol_defs.h:255
static const int ID
Definition cryptonote_protocol_defs.h:291
static const int ID
Definition cryptonote_protocol_defs.h:232
Definition cryptonote_protocol_defs.h:133
std::vector< tx_blob_entry > txs
Definition cryptonote_protocol_defs.h:137
bool pruned
Definition cryptonote_protocol_defs.h:134
blobdata block
Definition cryptonote_protocol_defs.h:135
Definition verification_context.h:66
bool m_verifivation_failed
Definition verification_context.h:68
bool m_bad_pow
Definition verification_context.h:72
bool m_added_to_main_chain
Definition verification_context.h:67
bool m_marked_as_orphaned
Definition verification_context.h:69
bool m_missing_txs
Definition verification_context.h:73
Definition cryptonote_basic.h:475
transaction miner_tx
Definition cryptonote_basic.h:489
std::vector< crypto::hash > tx_hashes
Definition cryptonote_basic.h:490
Definition cryptonote_protocol_defs.h:48
std::string connection_id
Definition cryptonote_protocol_defs.h:81
uint32_t pruning_seed
Definition cryptonote_protocol_defs.h:85
std::string address
Definition cryptonote_protocol_defs.h:54
uint8_t address_type
Definition cryptonote_protocol_defs.h:87
uint64_t recv_count
Definition cryptonote_protocol_defs.h:63
uint64_t live_time
Definition cryptonote_protocol_defs.h:71
uint32_t support_flags
Definition cryptonote_protocol_defs.h:79
uint32_t rpc_credits_per_hash
Definition cryptonote_protocol_defs.h:59
bool localhost
Definition cryptonote_protocol_defs.h:50
std::string port
Definition cryptonote_protocol_defs.h:57
uint64_t height
Definition cryptonote_protocol_defs.h:83
uint64_t send_idle_time
Definition cryptonote_protocol_defs.h:67
std::string host
Definition cryptonote_protocol_defs.h:55
std::string ip
Definition cryptonote_protocol_defs.h:56
uint64_t current_download
Definition cryptonote_protocol_defs.h:74
uint64_t avg_download
Definition cryptonote_protocol_defs.h:73
uint64_t recv_idle_time
Definition cryptonote_protocol_defs.h:64
uint16_t rpc_port
Definition cryptonote_protocol_defs.h:58
uint64_t send_count
Definition cryptonote_protocol_defs.h:66
std::string state
Definition cryptonote_protocol_defs.h:69
bool local_ip
Definition cryptonote_protocol_defs.h:51
bool ssl
Definition cryptonote_protocol_defs.h:52
bool incoming
Definition cryptonote_protocol_defs.h:49
std::string peer_id
Definition cryptonote_protocol_defs.h:61
uint64_t current_upload
Definition cryptonote_protocol_defs.h:77
uint64_t avg_upload
Definition cryptonote_protocol_defs.h:76
Definition connection_context.h:44
@ state_before_handshake
Definition connection_context.h:52
@ state_normal
Definition connection_context.h:56
@ state_standby
Definition connection_context.h:54
@ state_synchronizing
Definition connection_context.h:53
uint32_t m_rpc_credits_per_hash
Definition connection_context.h:113
uint16_t m_rpc_port
Definition connection_context.h:112
uint64_t m_remote_blockchain_height
Definition connection_context.h:105
uint32_t m_pruning_seed
Definition connection_context.h:111
boost::posix_time::ptime m_last_request_time
Definition connection_context.h:108
state m_state
Definition connection_context.h:101
Used to provide transaction info that skips the mempool to block handling code.
Definition tx_verification_utils.h:101
std::uint8_t nic_verified_hf_version
Definition tx_verification_utils.h:107
std::unordered_map< crypto::hash, std::pair< transaction, blobdata > > txs_by_txid
Definition tx_verification_utils.h:104
Definition cryptonote_protocol_defs.h:122
Definition verification_context.h:41
Definition cryptonote_basic.h:102
Definition misc_language.h:104
time_t m_last_send
Definition net_utils_base.h:374
time_t m_last_recv
Definition net_utils_base.h:373
uint64_t m_send_cnt
Definition net_utils_base.h:376
const bool m_is_income
Definition net_utils_base.h:370
const bool m_ssl
Definition net_utils_base.h:372
const boost::uuids::uuid m_connection_id
Definition net_utils_base.h:368
const time_t m_started
Definition net_utils_base.h:371
const network_address m_remote_address
Definition net_utils_base.h:369
double m_current_speed_down
Definition net_utils_base.h:377
double m_current_speed_up
Definition net_utils_base.h:378
uint64_t m_recv_cnt
Definition net_utils_base.h:375
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:153
std::string data
Definition base58.cpp:37
struct hash_func hashes[]
randomx_vm * vm
Definition tests.cpp:20
cryptonote::transaction tx
Definition transaction.cpp:40