40 #include <boost/format.hpp> 44 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY 45 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "daemon" 54 time_t last_seen =
static_cast<time_t
>(peer.
last_seen);
60 std::stringstream peer_id_str;
61 peer_id_str << std::hex << std::setw(16) << peer.
id;
62 peer_id_str >> id_str;
67 tools::msg_writer() << boost::format(
"%-10s %-25s %-25s %-5s %-4s %s") % prefix % id_str % addr_str % rpc_port % pruning_seed % elapsed;
74 <<
"previous hash: " << header.
prev_hash << std::endl
77 <<
"height: " << boost::lexical_cast<std::string>(header.
height) << std::endl
79 <<
"hash: " << header.
hash << std::endl
80 <<
"difficulty: " << boost::lexical_cast<std::string>(header.
difficulty) << std::endl
81 <<
"POW hash: " << header.
pow_hash << std::endl
82 <<
"block size: " << header.
block_size << std::endl
85 <<
"num txes: " << header.
num_txes << std::endl
89 std::string get_human_time_ago(time_t t, time_t now)
93 time_t dt = t > now ? t - now : now - t;
96 s = boost::lexical_cast<
std::string>(dt) +
" seconds";
97 else if (dt < 90 * 60)
98 s = boost::lexical_cast<
std::string>(dt/60) +
" minutes";
99 else if (dt < 36 * 3600)
100 s = boost::lexical_cast<
std::string>(dt/3600) +
" hours";
102 s = boost::lexical_cast<
std::string>(dt/(3600*24)) +
" days";
103 return s +
" " + (t > now ?
"in the future" :
"ago");
108 unsigned int hours, minutes, seconds;
115 snprintf(buffer,
sizeof(buffer),
"%02u:%02u:%02u", hours, minutes, seconds);
123 return base +
" -- " + status;
130 ,
const boost::optional<tools::login>& login
135 : m_rpc_client(NULL), m_rpc_server(rpc_server)
139 boost::optional<epee::net_utils::http::login> http_login{};
141 http_login.emplace(login->username, login->password.password());
146 if (rpc_server == NULL)
148 throw std::runtime_error(
"If not calling commands via RPC, rpc_server pointer must be non-null");
157 if (m_rpc_client != NULL)
167 std::string failure_message =
"Couldn't retrieve peer list";
170 if (!m_rpc_client->
rpc_request(req,
res,
"/get_peer_list", failure_message.c_str()))
186 auto peer =
res.white_list.cbegin();
187 const auto end = limit ? peer + std::min(limit,
res.white_list.size()) :
res.white_list.cend();
188 for (; peer != end; ++peer)
190 print_peer(
"white", *peer);
196 auto peer =
res.gray_list.cbegin();
197 const auto end = limit ? peer + std::min(limit,
res.gray_list.size()) :
res.gray_list.cend();
198 for (; peer != end; ++peer)
200 print_peer(
"gray", *peer);
211 std::string failure_message =
"Couldn't retrieve peer list";
214 if (!m_rpc_client->
rpc_request(req,
res,
"/get_peer_list", failure_message.c_str()))
239 std::string fail_message =
"Couldn't save blockchain";
243 if (!m_rpc_client->
rpc_request(req,
res,
"/save_bc", fail_message.c_str()))
271 if (!m_rpc_client->
rpc_request(req,
res,
"/set_log_hash_rate", fail_message.c_str()))
298 if (!m_rpc_client->
rpc_request(req,
res,
"/set_log_hash_rate", fail_message.c_str()))
321 std::string fail_message =
"Problem fetching info";
325 if (!m_rpc_client->
rpc_request(req,
res,
"/getinfo", fail_message.c_str()))
340 <<
", TH: " <<
res.top_block_hash
341 <<
", DIFF: " <<
res.difficulty
342 <<
", HR: " <<
res.difficulty /
res.target <<
" H/s";
349 if (hr>1e9)
return (boost::format(
"%.2f GH/s") % (hr/1e9)).str();
350 if (hr>1e6)
return (boost::format(
"%.2f MH/s") % (hr/1e6)).str();
351 if (hr>1e3)
return (boost::format(
"%.2f kH/s") % (hr/1e3)).str();
352 return (boost::format(
"%.0f H/s") % hr).str();
357 uint64_t blocks_per_day = 86400 / block_time;
360 return " (forking now)";
366 return (boost::format(
" (next fork in %u blocks)") % (
unsigned)dblocks).str();
367 if (dblocks <= blocks_per_day / 2)
368 return (boost::format(
" (next fork in %.1f hours)") % (dblocks / (
float)(blocks_per_day / 24))).str();
369 if (dblocks <= blocks_per_day * 30)
370 return (boost::format(
" (next fork in %.1f days)") % (dblocks / (
float)blocks_per_day)).str();
378 target_height = target_height ? target_height <
height ?
height : target_height :
height;
379 float pc = 100.0f *
height / target_height;
380 if (height < target_height && pc > 99.9f)
386 return get_sync_percentage(ires.height, ires.target_height);
397 bool has_mining_info =
true;
399 std::string fail_message =
"Problem fetching info";
402 bool mining_busy =
false;
405 if (!m_rpc_client->
rpc_request(ireq, ires,
"/getinfo", fail_message.c_str()))
409 if (!m_rpc_client->
json_rpc_request(hfreq, hfres,
"hard_fork_info", fail_message.c_str()))
414 has_mining_info = m_rpc_client->
rpc_request(mreq, mres,
"/mining_status", fail_message.c_str());
445 std::time_t uptime =
std::time(
nullptr) - ires.start_time;
446 uint64_t net_height = ires.target_height > ires.height ? ires.target_height : ires.height;
448 if (ires.was_bootstrap_ever_used)
450 bootstrap_msg =
", bootstrapping from " + ires.bootstrap_daemon_address;
453 bootstrap_msg += (boost::format(
", local height: %llu (%.1f%%)") % ires.height_without_bootstrap % get_sync_percentage(ires.height_without_bootstrap, net_height)).str();
457 bootstrap_msg +=
" was used before";
461 std::stringstream str;
462 str << boost::format(
"Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %u(out)+%u(in) connections")
463 % (
unsigned long long)ires.height
464 % (
unsigned long long)net_height
465 % get_sync_percentage(ires)
466 % (ires.testnet ?
"testnet" : ires.stagenet ?
"stagenet" :
"mainnet")
468 % (!has_mining_info ?
"mining info unavailable" : mining_busy ?
"syncing" : mres.active ? ( ( mres.is_background_mining_enabled ?
"smart " :
"" ) +
std::string(
"mining at ") + get_mining_speed(mres.speed)) :
"not mining")
469 % get_mining_speed(ires.difficulty / ires.target)
470 % (unsigned)hfres.version
471 % get_fork_extra_info(hfres.earliest_height, net_height, ires.target)
472 % (unsigned)ires.outgoing_connections_count
473 % (
unsigned)ires.incoming_connections_count
479 str << boost::format(
", uptime %ud %uh %um %us")
480 % (
unsigned int)floor(uptime / 60.0 / 60.0 / 24.0)
481 % (
unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0))
482 % (
unsigned int)floor(fmod((uptime / 60.0), 60.0))
483 % (
unsigned int)fmod(uptime, 60.0)
496 bool has_mining_info =
true;
498 std::string fail_message =
"Problem fetching info";
500 bool mining_busy =
false;
504 has_mining_info = m_rpc_client->
rpc_request(mreq, mres,
"/mining_status", fail_message.c_str());
525 if (!has_mining_info)
531 if (mining_busy || !mres.active)
537 tools::msg_writer() <<
"Mining at " << get_mining_speed(mres.speed) <<
" with " << mres.threads_count <<
" threads";
540 if (mres.active || mres.is_background_mining_enabled)
546 if (mres.is_background_mining_enabled)
550 tools::msg_writer() <<
" Idle threshold: " << (unsigned)mres.bg_idle_threshold <<
"% CPU";
551 tools::msg_writer() <<
" Min idle time: " << (unsigned)mres.bg_min_idle_seconds <<
" seconds";
552 tools::msg_writer() <<
" Ignore battery: " << (mres.bg_ignore_battery ?
"yes" :
"no");
555 if (!mining_busy && mres.active && mres.speed > 0 && mres.block_target > 0 && mres.difficulty > 0)
557 double ratio = mres.speed * mres.block_target / (double)mres.difficulty;
558 uint64_t daily = 86400ull / mres.block_target * mres.block_reward * ratio;
559 uint64_t monthly = 86400ull / mres.block_target * 30.5 * mres.block_reward * ratio;
560 uint64_t yearly = 86400ull / mres.block_target * 356 * mres.block_reward * ratio;
592 << std::setw(6) <<
"SSL" 593 << std::setw(20) <<
"Peer id" 594 << std::setw(20) <<
"Support Flags" 595 << std::setw(30) <<
"Recv/Sent (inactive,sec)" 596 << std::setw(25) <<
"State" 597 << std::setw(20) <<
"Livetime(sec)" 598 << std::setw(12) <<
"Down (kB/s)" 599 << std::setw(14) <<
"Down(now)" 600 << std::setw(10) <<
"Up (kB/s)" 601 << std::setw(13) <<
"Up(now)" 604 for (
auto &
info :
res.connections)
611 << std::setw(30) << std::left <<
address 612 << std::setw(6) << (
info.ssl ?
"yes" :
"no")
614 << std::setw(20) <<
info.support_flags
616 << std::setw(25) <<
info.state
617 << std::setw(20) <<
info.live_time
618 << std::setw(12) <<
info.avg_download
619 << std::setw(14) <<
info.current_download
620 << std::setw(10) <<
info.avg_upload
621 << std::setw(13) <<
info.current_upload
623 << std::left << (
info.localhost ?
"[LOCALHOST]" :
"")
624 << std::left << (
info.local_ip ?
"[LAN]" :
"");
643 if (!m_rpc_client->
json_rpc_request(net_stats_req, net_stats_res,
"get_net_stats", fail_message.c_str()))
647 if (!m_rpc_client->
json_rpc_request(limit_req, limit_res,
"get_limit", fail_message.c_str()))
667 uint64_t average = seconds > 0 ? net_stats_res.total_bytes_in / seconds : 0;
668 uint64_t limit = limit_res.limit_down * 1024;
669 double percent = (double)average / (
double)limit * 100.0;
670 tools::success_msg_writer() << boost::format(
"Received %u bytes (%s) in %u packets, average %s/s = %.2f%% of the limit of %s/s")
671 % net_stats_res.total_bytes_in
673 % net_stats_res.total_packets_in
678 average = seconds > 0 ? net_stats_res.total_bytes_out / seconds : 0;
679 limit = limit_res.limit_up * 1024;
680 percent = (double)average / (
double)limit * 100.0;
681 tools::success_msg_writer() << boost::format(
"Sent %u bytes (%s) in %u packets, average %s/s = %.2f%% of the limit of %s/s")
682 % net_stats_res.total_bytes_out
684 % net_stats_res.total_packets_out
697 req.start_height = start_block_index;
698 req.end_height = end_block_index;
699 req.fill_pow_hash =
false;
705 if (!m_rpc_client->
json_rpc_request(req,
res,
"getblockheadersrange", fail_message.c_str()))
720 for (
auto & header :
res.headers)
726 <<
", size: " << header.block_size <<
", weight: " << header.block_weight <<
" (long term " << header.long_term_weight <<
"), transactions: " << header.num_txes << std::endl
727 <<
"major version: " << (unsigned)header.major_version <<
", minor version: " << (
unsigned)header.minor_version << std::endl
728 <<
"block id: " << header.hash <<
", previous block id: " << header.prev_hash << std::endl
729 <<
"difficulty: " << header.difficulty <<
", nonce " << header.nonce <<
", reward " <<
cryptonote::print_etn(header.reward) << std::endl;
745 if (!m_rpc_client->
rpc_request(req,
res,
"/set_log_level", fail_message.c_str()))
767 req.categories = categories;
773 if (!m_rpc_client->
rpc_request(req,
res,
"/set_log_categories", fail_message.c_str()))
800 if (!m_rpc_client->
rpc_request(req,
res,
"/getheight", fail_message.c_str()))
825 req.fill_pow_hash =
true;
847 print_block_header(
res.block_header);
859 req.fill_pow_hash =
true;
881 print_block_header(
res.block_header);
893 std::string fail_message =
"Problem fetching transaction";
896 req.decode_as_json =
false;
901 if (!m_rpc_client->
rpc_request(req,
res,
"/gettransactions", fail_message.c_str()))
915 if (1 ==
res.txs.size() || 1 ==
res.txs_as_hex.size())
917 if (1 ==
res.txs.size())
920 if (
res.txs.front().in_pool)
923 tools::success_msg_writer() <<
"Found in blockchain at height " <<
res.txs.front().block_height << (
res.txs.front().prunable_as_hex.empty() ?
" (pruned)" :
"");
926 const std::string &as_hex = (1 ==
res.txs.size()) ?
res.txs.front().as_hex :
res.txs_as_hex.front();
927 const std::string &pruned_as_hex = (1 ==
res.txs.size()) ?
res.txs.front().pruned_as_hex :
"";
928 const std::string &prunable_as_hex = (1 ==
res.txs.size()) ?
res.txs.front().prunable_as_hex :
"";
938 std::string output = pruned_as_hex + prunable_as_hex;
950 bool pruned = !pruned_as_hex.empty() && prunable_as_hex.empty();
985 std::string fail_message =
"Problem checking key image";
990 if (!m_rpc_client->
rpc_request(req,
res,
"/is_key_image_spent", fail_message.c_str()))
1004 if (1 ==
res.spent_status.size())
1021 std::string fail_message =
"Problem checking public_output";
1027 req.public_outputs.push_back(po);
1030 if (!m_rpc_client->
rpc_request(req,
res,
"/is_public_output_spent", fail_message.c_str()))
1044 if (1 ==
res.spent_status.size())
1061 std::string fail_message =
"Problem fetching transaction pool";
1065 if (!m_rpc_client->
rpc_request(req,
res,
"/get_transaction_pool", fail_message.c_str()))
1079 if (
res.transactions.empty() &&
res.spent_key_images.empty())
1083 if (!
res.transactions.empty())
1085 const time_t now =
time(NULL);
1087 for (
auto & tx_info :
res.transactions)
1090 << tx_info.tx_json << std::endl
1091 <<
"blob_size: " << tx_info.blob_size << std::endl
1092 <<
"weight: " << tx_info.weight << std::endl
1095 <<
"receive_time: " << tx_info.receive_time <<
" (" << get_human_time_ago(tx_info.receive_time, now) <<
")" << std::endl
1096 <<
"relayed: " << [&](
const cryptonote::tx_info &tx_info)->
std::string {
if (!tx_info.relayed)
return "no";
return boost::lexical_cast<
std::string>(tx_info.last_relayed_time) +
" (" + get_human_time_ago(tx_info.last_relayed_time, now) +
")"; } (tx_info) << std::endl
1097 <<
"do_not_relay: " << (tx_info.do_not_relay ?
'T' :
'F') << std::endl
1098 <<
"kept_by_block: " << (tx_info.kept_by_block ?
'T' :
'F') << std::endl
1099 <<
"double_spend_seen: " << (tx_info.double_spend_seen ?
'T' :
'F') << std::endl
1100 <<
"nonexistent_utxo_seen: " << (tx_info.nonexistent_utxo_seen ?
'T' :
'F') << std::endl
1101 <<
"max_used_block_height: " << tx_info.max_used_block_height << std::endl
1102 <<
"max_used_block_id: " << tx_info.max_used_block_id_hash << std::endl
1103 <<
"last_failed_height: " << tx_info.last_failed_height << std::endl
1104 <<
"last_failed_id: " << tx_info.last_failed_id_hash << std::endl;
1107 if (!
res.spent_key_images.empty())
1131 if (
res.transactions.empty())
1144 std::string fail_message =
"Problem fetching transaction pool";
1148 if (!m_rpc_client->
rpc_request(req,
res,
"/get_transaction_pool", fail_message.c_str()))
1162 if (
res.transactions.empty())
1168 const time_t now =
time(NULL);
1169 for (
auto & tx_info :
res.transactions)
1172 <<
"blob_size: " << tx_info.blob_size << std::endl
1173 <<
"weight: " << tx_info.weight << std::endl
1176 <<
"receive_time: " << tx_info.receive_time <<
" (" << get_human_time_ago(tx_info.receive_time, now) <<
")" << std::endl
1177 <<
"relayed: " << [&](
const cryptonote::tx_info &tx_info)->
std::string {
if (!tx_info.relayed)
return "no";
return boost::lexical_cast<
std::string>(tx_info.last_relayed_time) +
" (" + get_human_time_ago(tx_info.last_relayed_time, now) +
")"; } (tx_info) << std::endl
1178 <<
"do_not_relay: " << (tx_info.do_not_relay ?
'T' :
'F') << std::endl
1179 <<
"kept_by_block: " << (tx_info.kept_by_block ?
'T' :
'F') << std::endl
1180 <<
"double_spend_seen: " << (tx_info.double_spend_seen ?
'T' :
'F') << std::endl
1181 <<
"nonexistent_utxo_seen: " << (tx_info.nonexistent_utxo_seen ?
'T' :
'F') << std::endl
1182 <<
"max_used_block_height: " << tx_info.max_used_block_height << std::endl
1183 <<
"max_used_block_id: " << tx_info.max_used_block_id_hash << std::endl
1184 <<
"last_failed_height: " << tx_info.last_failed_height << std::endl
1185 <<
"last_failed_id: " << tx_info.last_failed_id_hash << std::endl;
1198 std::string fail_message =
"Problem fetching transaction pool stats";
1202 if (!m_rpc_client->
rpc_request(req,
res,
"/get_transaction_pool_stats", fail_message.c_str()))
1206 if (!m_rpc_client->
rpc_request(ireq, ires,
"/getinfo", fail_message.c_str()))
1213 res.pool_stats = {};
1226 size_t n_transactions =
res.pool_stats.txs_total;
1228 size_t avg_bytes = n_transactions ?
res.pool_stats.bytes_total / n_transactions : 0;
1231 const uint64_t full_reward_zone = ires.block_weight_limit / 2;
1232 if (
res.pool_stats.bytes_total <= full_reward_zone)
1234 backlog_message =
"no backlog";
1238 uint64_t backlog = (
res.pool_stats.bytes_total + full_reward_zone - 1) / full_reward_zone;
1239 backlog_message = (boost::format(
"estimated %u block (%u minutes) backlog") % backlog % (backlog *
DIFFICULTY_TARGET_V6 / 60)).str();
1242 tools::msg_writer() << n_transactions <<
" tx(es), " <<
res.pool_stats.bytes_total <<
" bytes total (min " <<
res.pool_stats.bytes_min <<
", max " <<
res.pool_stats.bytes_max <<
", avg " << avg_bytes <<
", median " <<
res.pool_stats.bytes_med <<
")" << std::endl
1244 <<
res.pool_stats.num_double_spends <<
" double spends, " <<
res.pool_stats.num_not_relayed <<
" not relayed, " <<
res.pool_stats.num_failing <<
" failing, " <<
res.pool_stats.num_10m <<
" older than 10 minutes (oldest " << (
res.pool_stats.oldest == 0 ?
"-" : get_human_time_ago(
res.pool_stats.oldest, now)) <<
"), " << backlog_message;
1246 if (n_transactions > 1 &&
res.pool_stats.histo.size())
1248 std::vector<uint64_t> times;
1250 size_t i, n =
res.pool_stats.histo.size(), denom;
1252 if (
res.pool_stats.histo_98pc)
1254 numer =
res.pool_stats.histo_98pc;
1256 for (i=0; i<denom; i++)
1257 times[i] = i * numer / denom;
1258 times[i] = now -
res.pool_stats.oldest;
1261 numer = now -
res.pool_stats.oldest;
1263 for (i=0; i<denom; i++)
1264 times[i] = i * numer / denom;
1269 tools::msg_writer() << get_time_hms(times[i]) << std::setw(8) <<
res.pool_stats.histo[i].txs << std::setw(12) <<
res.pool_stats.histo[i].bytes;
1281 req.threads_count = num_threads;
1282 req.do_background_mining = do_background_mining;
1283 req.ignore_battery = ignore_battery;
1285 std::string fail_message =
"Mining did not start";
1289 if (m_rpc_client->
rpc_request(req,
res,
"/start_mining", fail_message.c_str()))
1314 if (!m_rpc_client->
rpc_request(req,
res,
"/stop_mining", fail_message.c_str()))
1355 if(!m_rpc_client->
rpc_request(req,
res,
"/stop_daemon", fail_message.c_str()))
1384 if(daemon_is_alive) {
1399 std::string failure_message =
"Couldn't get limit";
1403 if (!m_rpc_client->
rpc_request(req,
res,
"/get_limit", failure_message.c_str()))
1427 req.limit_down = limit_down;
1428 req.limit_up = limit_up;
1430 std::string failure_message =
"Couldn't set limit";
1434 if (!m_rpc_client->
rpc_request(req,
res,
"/set_limit", failure_message.c_str()))
1458 std::string failure_message =
"Couldn't get limit";
1462 if (!m_rpc_client->
rpc_request(req,
res,
"/get_limit", failure_message.c_str()))
1485 std::string failure_message =
"Couldn't get limit";
1489 if (!m_rpc_client->
rpc_request(req,
res,
"/get_limit", failure_message.c_str()))
1514 req.out_peers = limit;
1520 if (!m_rpc_client->
rpc_request(req,
res,
"/out_peers", fail_message.c_str()))
1546 req.in_peers = limit;
1552 if (!m_rpc_client->
rpc_request(req,
res,
"/in_peers", fail_message.c_str()))
1579 if (!m_rpc_client->
rpc_request(req,
res,
"/start_save_graph", fail_message.c_str()))
1606 if (!m_rpc_client->
rpc_request(req,
res,
"/stop_save_graph", fail_message.c_str()))
1651 ", " <<
res.votes <<
"/" <<
res.window <<
" votes, threshold " <<
res.threshold;
1680 for (
auto i =
res.bans.begin(); i !=
res.bans.end(); ++i)
1703 ban.seconds = seconds;
1704 req.bans.push_back(
ban);
1740 req.bans.push_back(
ban);
1769 req.txids.push_back(txid);
1798 req.amounts = amounts;
1799 req.min_count = min_count;
1800 req.max_count = max_count;
1801 req.unlocked =
false;
1802 req.recent_cutoff = 0;
1806 if (!m_rpc_client->
json_rpc_request(req,
res,
"get_output_histogram", fail_message.c_str()))
1820 std::sort(
res.histogram.begin(),
res.histogram.end(),
1822 for (
const auto &e:
res.histogram)
1843 if (!m_rpc_client->
json_rpc_request(req,
res,
"get_coinbase_tx_sum", fail_message.c_str()))
1877 if (!m_rpc_client->
rpc_request(ireq, ires,
"/getinfo", fail_message.c_str()))
1881 if (!m_rpc_client->
json_rpc_request(req,
res,
"get_alternate_chains", fail_message.c_str()))
1903 for (
const auto &chain:
res.chains)
1905 uint64_t start_height = (chain.height - chain.length + 1);
1906 tools::msg_writer() << chain.length <<
" blocks long, from height " << start_height <<
" (" << (ires.height - start_height - 1)
1907 <<
" deep), diff " << chain.difficulty <<
": " << chain.block_hash;
1913 if (i !=
res.chains.end())
1915 const auto &chain = *i;
1917 uint64_t start_height = (chain.height - chain.length + 1);
1918 tools::msg_writer() << chain.length <<
" blocks long, from height " << start_height <<
" (" << (ires.height - start_height - 1)
1919 <<
" deep), diff " << chain.difficulty <<
":";
1922 tools::msg_writer() <<
"Chain parent on main chain: " << chain.main_chain_parent_block;
1942 std::string fail_message =
"Problem fetching info";
1944 fereq.grace_blocks = 0;
1948 if (!m_rpc_client->
rpc_request(ireq, ires,
"/getinfo", fail_message.c_str()))
1952 if (!m_rpc_client->
json_rpc_request(fereq, feres,
"get_fee_estimate", fail_message.c_str()))
1956 if (!m_rpc_client->
json_rpc_request(hfreq, hfres,
"hard_fork_info", fail_message.c_str()))
1980 tools::msg_writer() <<
"Height: " << ires.height <<
", diff " << ires.difficulty <<
", cum. diff " << ires.cumulative_difficulty
1981 <<
", target " << ires.target <<
" sec" <<
", dyn fee " <<
cryptonote::print_etn(feres.fee) <<
"/" << (hfres.enabled ?
"byte" :
"kB");
1985 if (nblocks > ires.height)
1986 nblocks = ires.height;
1988 bhreq.start_height = ires.height - nblocks;
1989 bhreq.end_height = ires.height - 1;
1990 bhreq.fill_pow_hash =
false;
1993 if (!m_rpc_client->
json_rpc_request(bhreq, bhres,
"getblockheadersrange", fail_message.c_str()))
2008 double avgnumtxes = 0;
2009 double avgreward = 0;
2010 std::vector<uint64_t> weights;
2011 weights.reserve(nblocks);
2012 uint64_t earliest = std::numeric_limits<uint64_t>::max(), latest = 0;
2013 std::vector<unsigned> major_versions(256, 0), minor_versions(256, 0);
2014 for (
const auto &bhr: bhres.headers)
2016 avgdiff += bhr.difficulty;
2017 avgnumtxes += bhr.num_txes;
2018 avgreward += bhr.reward;
2019 weights.push_back(bhr.block_weight);
2020 static_assert(
sizeof(bhr.major_version) == 1,
"major_version expected to be uint8_t");
2021 static_assert(
sizeof(bhr.minor_version) == 1,
"major_version expected to be uint8_t");
2022 major_versions[(unsigned)bhr.major_version]++;
2023 minor_versions[(
unsigned)bhr.minor_version]++;
2024 earliest = std::min(earliest, bhr.timestamp);
2025 latest = std::max(latest, bhr.timestamp);
2028 avgnumtxes /= nblocks;
2029 avgreward /= nblocks;
2031 tools::msg_writer() <<
"Last " << nblocks <<
": avg. diff " << (
uint64_t)avgdiff <<
", " << (latest - earliest) / nblocks <<
" avg sec/block, avg num txes " << avgnumtxes
2032 <<
", avg. reward " <<
cryptonote::print_etn(avgreward) <<
", median block weight " << median_block_weight;
2034 unsigned int max_major = 256, max_minor = 256;
2035 while (max_major > 0 && !major_versions[--max_major]);
2036 while (max_minor > 0 && !minor_versions[--max_minor]);
2038 for (
unsigned n = 0; n <= max_major; ++n)
2039 if (major_versions[n])
2040 s += (s.empty() ?
"" :
", ") + boost::lexical_cast<std::string>(major_versions[n]) +
std::string(
" v") + boost::lexical_cast<
std::string>(n);
2043 for (
unsigned n = 0; n <= max_minor; ++n)
2044 if (minor_versions[n])
2045 s += (s.empty() ?
"" :
", ") + boost::lexical_cast<std::string>(minor_versions[n]) +
std::string(
" v") + boost::lexical_cast<
std::string>(n);
2057 std::string fail_message =
"Problem fetching info";
2059 req.command = command;
2063 if (!m_rpc_client->
rpc_request(req,
res,
"/update", fail_message.c_str()))
2088 if (command ==
"check")
2091 if (!
res.path.empty())
2095 if (command ==
"download")
2110 req.txids.push_back(txid);
2158 for (
const auto &p:
res.peers)
2159 current_download += p.info.current_download;
2161 if (
res.next_needed_pruning_seed)
2165 for (
const auto &p:
res.peers)
2169 for (
const auto &s:
res.spans)
2170 if (s.connection_id == p.info.connection_id)
2171 nblocks += s.nblocks, size += s.size;
2175 p.info.current_download <<
" kB/s, " << nblocks <<
" blocks / " << size/1e6 <<
" MB queued";
2179 for (
const auto &s:
res.spans)
2180 total_size += s.size;
2183 for (
const auto &s:
res.spans)
2189 tools::success_msg_writer() <<
address <<
" " << s.nblocks <<
"/" << pruning_seed <<
" (" << s.start_block_height <<
" - " << (s.start_block_height + s.nblocks - 1) <<
") -";
2193 tools::success_msg_writer() <<
address <<
" " << s.nblocks <<
"/" << pruning_seed <<
" (" << s.start_block_height <<
" - " << (s.start_block_height + s.nblocks - 1) <<
", " << (
uint64_t)(s.size/1e3) <<
" kB) " << (
unsigned)(s.rate/1e3) <<
" kB/s (" << s.speed/100.0f <<
")";
2209 if (!m_rpc_client->
rpc_request(req,
res,
"/pop_blocks", fail_message.c_str()))
2233 req.validator_key =
key;
2236 if (!m_rpc_client->
json_rpc_request(req,
res,
"set_validator_key", fail_message.c_str())) {
2305 if (
res.pruning_seed)
2323 if (!m_rpc_client->
json_rpc_request(req,
res,
"generate_ed25519_keypair", fail_message.c_str())) {
bool output_histogram(const std::vector< uint64_t > &amounts, uint64_t min_count, uint64_t max_count)
bool on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request &req, COMMAND_RPC_POP_BLOCKS::response &res, const connection_context *ctx=NULL)
bool update(const std::string &command)
bool on_get_block_headers_range(const COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::request &req, COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool print_blockchain_info(uint64_t start_block_index, uint64_t end_block_index)
bool on_get_peer_list(const COMMAND_RPC_GET_PEER_LIST::request &req, COMMAND_RPC_GET_PEER_LIST::response &res, const connection_context *ctx=NULL)
bool relay_tx(const std::string &txid)
~t_rpc_command_executor()
const CharType(& source)[N]
bool unban(const std::string &ip)
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
bool set_log_categories(const std::string &categories)
bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining=false, bool ignore_battery=false)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool check_blockchain_pruning()
bool set_log_level(int8_t level)
bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request &req, COMMAND_RPC_STOP_DAEMON::response &res, const connection_context *ctx=NULL)
#define CORE_RPC_STATUS_BUSY
#define CRYPTONOTE_PRUNING_LOG_STRIPES
uint64_t num_blocks(const std::vector< test_event_entry > &events)
bool on_start_mining(const COMMAND_RPC_START_MINING::request &req, COMMAND_RPC_START_MINING::response &res, const connection_context *ctx=NULL)
bool on_mining_status(const COMMAND_RPC_MINING_STATUS::request &req, COMMAND_RPC_MINING_STATUS::response &res, const connection_context *ctx=NULL)
bool on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request &req, COMMAND_RPC_GET_TRANSACTIONS::response &res, const connection_context *ctx=NULL)
bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request &req, COMMAND_RPC_SET_LOG_LEVEL::response &res, const connection_context *ctx=NULL)
bool set_limit(int64_t limit_down, int64_t limit_up)
bool set_validator_key(const std::string &key)
bool in_peers(uint64_t limit)
bool print_blockchain_dynamic_stats(uint64_t nblocks)
bool on_update(const COMMAND_RPC_UPDATE::request &req, COMMAND_RPC_UPDATE::response &res, const connection_context *ctx=NULL)
bool on_is_public_output_spent(const COMMAND_RPC_IS_PUBLIC_OUTPUT_SPENT::request &req, COMMAND_RPC_IS_PUBLIC_OUTPUT_SPENT::response &res, const connection_context *ctx=NULL)
bool sign_message(const std::string privateKey, const std::string message)
bool on_get_limit(const COMMAND_RPC_GET_LIMIT::request &req, COMMAND_RPC_GET_LIMIT::response &res, const connection_context *ctx=NULL)
#define CORE_RPC_STATUS_OK
for(i=1;i< 1;++i) fe_sq(t0
bool hard_fork_info(uint8_t version)
bool print_coinbase_tx_sum(uint64_t height, uint64_t count)
bool out_peers(uint64_t limit)
bool on_set_bans(const COMMAND_RPC_SETBANS::request &req, COMMAND_RPC_SETBANS::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request &req, COMMAND_RPC_STOP_MINING::response &res, const connection_context *ctx=NULL)
bool on_get_block(const COMMAND_RPC_GET_BLOCK::request &req, COMMAND_RPC_GET_BLOCK::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
mdb_size_t count(MDB_cursor *cur)
bool print_transaction_pool_long()
bool on_sync_info(const COMMAND_RPC_SYNC_INFO::request &req, COMMAND_RPC_SYNC_INFO::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool pop_blocks(uint64_t num_blocks)
#define DIFFICULTY_TARGET_V6
bool on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request &req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response &res, const connection_context *ctx=NULL)
bool on_save_bc(const COMMAND_RPC_SAVE_BC::request &req, COMMAND_RPC_SAVE_BC::response &res, const connection_context *ctx=NULL)
bool on_out_peers(const COMMAND_RPC_OUT_PEERS::request &req, COMMAND_RPC_OUT_PEERS::response &res, const connection_context *ctx=NULL)
std::vector< std::string > txs_hashes
std::string obj_to_json_str(T &obj)
unsigned __int64 uint64_t
bool on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request &req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response &res, const connection_context *ctx=NULL)
bool on_get_bans(const COMMAND_RPC_GETBANS::request &req, COMMAND_RPC_GETBANS::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool print_transaction_pool_short()
std::string get_time_interval_string(const time_t &time_)
bool ban(const std::string &ip, time_t seconds)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT
bool on_generate_ed25519_keypair(const COMMAND_RPC_GENERATE_ED25519_KEYPAIR::request &req, COMMAND_RPC_GENERATE_ED25519_KEYPAIR::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
version
Supported socks variants.
bool on_get_info(const COMMAND_RPC_GET_INFO::request &req, COMMAND_RPC_GET_INFO::response &res, const connection_context *ctx=NULL)
std::string message("Message requiring signing")
boost::endian::big_uint32_t ip
boost::endian::big_uint16_t port
bool print_block_by_hash(crypto::hash block_hash, bool include_hex)
bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request &req, COMMAND_RPC_GET_TRANSACTION_POOL::response &res, const connection_context *ctx=NULL)
bool print_peer_list_stats()
type_vec_type median(std::vector< type_vec_type > &v)
bool on_set_limit(const COMMAND_RPC_SET_LIMIT::request &req, COMMAND_RPC_SET_LIMIT::response &res, const connection_context *ctx=NULL)
bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request &req, COMMAND_RPC_STOP_SAVE_GRAPH::response &res, const connection_context *ctx=NULL)
bool on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request &req, COMMAND_RPC_GET_COINBASE_TX_SUM::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
const T & move(const T &t)
bool on_prune_blockchain(const COMMAND_RPC_PRUNE_BLOCKCHAIN::request &req, COMMAND_RPC_PRUNE_BLOCKCHAIN::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_get_height(const COMMAND_RPC_GET_HEIGHT::request &req, COMMAND_RPC_GET_HEIGHT::response &res, const connection_context *ctx=NULL)
uint64_t relative_out_index
bool print_transaction_pool_stats()
bool on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request &req, COMMAND_RPC_SET_LOG_CATEGORIES::response &res, const connection_context *ctx=NULL)
bool on_get_output_histogram(const COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request &req, COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_relay_tx(const COMMAND_RPC_RELAY_TX::request &req, COMMAND_RPC_RELAY_TX::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool is_key_image_spent(const crypto::key_image &ki)
bool on_flush_txpool(const COMMAND_RPC_FLUSH_TRANSACTION_POOL::request &req, COMMAND_RPC_FLUSH_TRANSACTION_POOL::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_get_connections(const COMMAND_RPC_GET_CONNECTIONS::request &req, COMMAND_RPC_GET_CONNECTIONS::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool is_public_output_spent(const cryptonote::txin_to_key_public &txin)
bool flush_txpool(const std::string &txid)
t_rpc_command_executor(uint32_t ip, uint16_t port, const boost::optional< tools::login > &user, const epee::net_utils::ssl_options_t &ssl_options, bool is_rpc=true, cryptonote::core_rpc_server *rpc_server=NULL)
bool on_get_base_fee_estimate(const COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request &req, COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request &req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_sign_message(const COMMAND_RPC_SIGN_MESSAGE::request &req, COMMAND_RPC_SIGN_MESSAGE::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_set_log_hash_rate(const COMMAND_RPC_SET_LOG_HASH_RATE::request &req, COMMAND_RPC_SET_LOG_HASH_RATE::response &res, const connection_context *ctx=NULL)
bool print_peer_list(bool white=true, bool gray=true, size_t limit=0)
std::string to_string(t_connection_type type)
bool generate_ed25519_keypair()
bool on_set_validator_key(const COMMAND_RPC_SET_VALIDATOR_KEY::request &req, COMMAND_RPC_SET_VALIDATOR_KEY::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool on_in_peers(const COMMAND_RPC_IN_PEERS::request &req, COMMAND_RPC_IN_PEERS::response &res, const connection_context *ctx=NULL)
#define HF_VERSION_PER_BYTE_FEE
bool alt_chain_info(const std::string &tip)
bool on_get_net_stats(const COMMAND_RPC_GET_NET_STATS::request &req, COMMAND_RPC_GET_NET_STATS::response &res, const connection_context *ctx=NULL)
bool print_block_by_height(uint64_t height, bool include_hex)
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT
bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request &req, COMMAND_RPC_START_SAVE_GRAPH::response &res, const connection_context *ctx=NULL)
bool on_hard_fork_info(const COMMAND_RPC_HARD_FORK_INFO::request &req, COMMAND_RPC_HARD_FORK_INFO::response &res, epee::json_rpc::error &error_resp, const connection_context *ctx=NULL)
bool print_transaction(crypto::hash transaction_hash, bool include_hex, bool include_json)