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;
64 std::string addr_str = ip_str +
":" + port_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
75 <<
"nonce: " << boost::lexical_cast<std::string>(header.
nonce) << std::endl
77 <<
"height: " << boost::lexical_cast<std::string>(header.
height) << std::endl
78 <<
"depth: " << boost::lexical_cast<std::string>(header.
depth) << 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");
106 std::string get_time_hms(time_t t)
108 unsigned int hours, minutes, seconds;
115 snprintf(buffer,
sizeof(buffer),
"%02u:%02u:%02u", hours, minutes, seconds);
116 return std::string(buffer);
119 std::string make_error(
const std::string &base,
const std::string &status)
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()))
267 std::string fail_message =
"Unsuccessful";
271 if (!m_rpc_client->rpc_request(req,
res,
"/set_log_hash_rate", fail_message.c_str()))
294 std::string fail_message =
"Unsuccessful";
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";
347static std::string get_mining_speed(
uint64_t hr)
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;
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());
423 if (!m_rpc_server->on_hard_fork_info(hfreq, hfres, error_resp) || hfres.status !=
CORE_RPC_STATUS_OK)
428 if (!m_rpc_server->on_mining_status(mreq, mres))
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;
447 std::string bootstrap_msg;
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());
508 if (!m_rpc_server->on_mining_status(mreq, mres))
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;
573 std::string fail_message =
"Unsuccessful";
577 if (!m_rpc_client->json_rpc_request(req,
res,
"get_connections", fail_message.c_str()))
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)
606 std::string
address =
info.incoming ?
"INC " :
"OUT ";
611 << std::setw(30) << std::left <<
address
612 << std::setw(6) << (
info.ssl ?
"yes" :
"no")
614 << std::setw(20) <<
info.support_flags
615 << std::setw(30) << std::to_string(
info.recv_count) +
"(" + std::to_string(
info.recv_idle_time) +
")/" + std::to_string(
info.send_count) +
"(" + std::to_string(
info.send_idle_time) +
")"
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]" :
"");
639 std::string fail_message =
"Unsuccessful";
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()))
654 if (!m_rpc_server->on_get_net_stats(net_stats_req, net_stats_res) || net_stats_res.status !=
CORE_RPC_STATUS_OK)
659 if (!m_rpc_server->on_get_limit(limit_req, limit_res) || limit_res.status !=
CORE_RPC_STATUS_OK)
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;
701 std::string fail_message =
"Unsuccessful";
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;
741 std::string fail_message =
"Unsuccessful";
745 if (!m_rpc_client->rpc_request(req,
res,
"/set_log_level", fail_message.c_str()))
767 req.categories = categories;
769 std::string fail_message =
"Unsuccessful";
773 if (!m_rpc_client->rpc_request(req,
res,
"/set_log_categories", fail_message.c_str()))
796 std::string fail_message =
"Unsuccessful";
800 if (!m_rpc_client->rpc_request(req,
res,
"/getheight", fail_message.c_str()))
825 req.fill_pow_hash =
true;
827 std::string fail_message =
"Unsuccessful";
831 if (!m_rpc_client->json_rpc_request(req,
res,
"getblock", fail_message.c_str()))
847 print_block_header(
res.block_header);
859 req.fill_pow_hash =
true;
861 std::string fail_message =
"Unsuccessful";
865 if (!m_rpc_client->json_rpc_request(req,
res,
"getblock", fail_message.c_str()))
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;
949 std::string
source = as_hex.empty() ? pruned_as_hex + prunable_as_hex : 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())
1125 for (
const std::string& tx_id : kinfo.
txs_hashes)
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;
1230 std::string backlog_message;
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()))
1310 std::string fail_message =
"Mining did not stop";
1314 if (!m_rpc_client->rpc_request(req,
res,
"/stop_mining", fail_message.c_str()))
1351 std::string fail_message =
"Daemon did not stop";
1355 if(!m_rpc_client->rpc_request(req,
res,
"/stop_daemon", fail_message.c_str()))
1382 bool daemon_is_alive = m_rpc_client->check_connection();
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;
1516 std::string fail_message =
"Unsuccessful";
1520 if (!m_rpc_client->rpc_request(req,
res,
"/out_peers", fail_message.c_str()))
1546 req.in_peers = limit;
1548 std::string fail_message =
"Unsuccessful";
1552 if (!m_rpc_client->rpc_request(req,
res,
"/in_peers", fail_message.c_str()))
1575 std::string fail_message =
"Unsuccessful";
1579 if (!m_rpc_client->rpc_request(req,
res,
"/start_save_graph", fail_message.c_str()))
1602 std::string fail_message =
"Unsuccessful";
1606 if (!m_rpc_client->rpc_request(req,
res,
"/stop_save_graph", fail_message.c_str()))
1628 std::string fail_message =
"Unsuccessful";
1635 if (!m_rpc_client->json_rpc_request(req,
res,
"hard_fork_info", fail_message.c_str()))
1651 ", " <<
res.votes <<
"/" <<
res.window <<
" votes, threshold " <<
res.threshold;
1661 std::string fail_message =
"Unsuccessful";
1666 if (!m_rpc_client->json_rpc_request(req,
res,
"get_bans", fail_message.c_str()))
1680 for (
auto i =
res.bans.begin(); i !=
res.bans.end(); ++i)
1693 std::string fail_message =
"Unsuccessful";
1703 ban.seconds = seconds;
1704 req.bans.push_back(
ban);
1708 if (!m_rpc_client->json_rpc_request(req,
res,
"set_bans", fail_message.c_str()))
1729 std::string fail_message =
"Unsuccessful";
1740 req.bans.push_back(
ban);
1744 if (!m_rpc_client->json_rpc_request(req,
res,
"set_bans", fail_message.c_str()))
1765 std::string fail_message =
"Unsuccessful";
1769 req.txids.push_back(txid);
1773 if (!m_rpc_client->json_rpc_request(req,
res,
"flush_txpool", fail_message.c_str()))
1795 std::string fail_message =
"Unsuccessful";
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)
1839 std::string fail_message =
"Unsuccessful";
1843 if (!m_rpc_client->json_rpc_request(req,
res,
"get_coinbase_tx_sum", fail_message.c_str()))
1873 std::string fail_message =
"Unsuccessful";
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()))
1893 if (!m_rpc_server->on_get_alternate_chains(req,
res, error_resp))
1902 tools::msg_writer() << boost::lexical_cast<std::string>(
res.chains.size()) <<
" alternate chains found:";
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 <<
":";
1920 for (
const std::string &block_id: chain.block_hashes)
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()))
1968 if (!m_rpc_server->on_get_base_fee_estimate(fereq, feres, error_resp) || feres.status !=
CORE_RPC_STATUS_OK)
1973 if (!m_rpc_server->on_hard_fork_info(hfreq, hfres, error_resp) || hfres.status !=
CORE_RPC_STATUS_OK)
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()))
2000 if (!m_rpc_server->on_get_block_headers_range(bhreq, bhres, error_resp) || bhres.status !=
CORE_RPC_STATUS_OK)
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")
2107 std::string fail_message =
"Unsuccessful";
2110 req.txids.push_back(txid);
2114 if (!m_rpc_client->json_rpc_request(req,
res,
"relay_tx", fail_message.c_str()))
2136 std::string fail_message =
"Unsuccessful";
2141 if (!m_rpc_client->json_rpc_request(req,
res,
"sync_info", fail_message.c_str()))
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 <<
")";
2204 std::string fail_message =
"pop_blocks failed";
2209 if (!m_rpc_client->rpc_request(req,
res,
"/pop_blocks", fail_message.c_str()))
2230 std::string fail_message =
"Unsuccessful";
2233 req.validator_key =
key;
2236 if (!m_rpc_client->json_rpc_request(req,
res,
"set_validator_key", fail_message.c_str())) {
2255 std::string fail_message =
"Unsuccessful";
2262 if (!m_rpc_client->json_rpc_request(req,
res,
"prune_blockchain", fail_message.c_str()))
2284 std::string fail_message =
"Unsuccessful";
2291 if (!m_rpc_client->json_rpc_request(req,
res,
"prune_blockchain", fail_message.c_str()))
2305 if (
res.pruning_seed)
2319 std::string fail_message =
"Unsuccessful";
2323 if (!m_rpc_client->json_rpc_request(req,
res,
"generate_ed25519_keypair", fail_message.c_str())) {
2342 std::string fail_message =
"Unsuccessful";
2349 if (!m_rpc_client->json_rpc_request(req,
res,
"sign_message", fail_message.c_str())) {
uint64_t num_blocks(const std::vector< test_event_entry > &events)
bool set_limit(int64_t limit_down, int64_t limit_up)
bool check_blockchain_pruning()
bool is_public_output_spent(const cryptonote::txin_to_key_public &txin)
bool ban(const std::string &ip, time_t seconds)
bool is_key_image_spent(const crypto::key_image &ki)
bool print_transaction_pool_stats()
bool output_histogram(const std::vector< uint64_t > &amounts, uint64_t min_count, uint64_t max_count)
bool print_block_by_height(uint64_t height, bool include_hex)
bool print_transaction(crypto::hash transaction_hash, bool include_hex, bool include_json)
bool print_transaction_pool_short()
bool print_blockchain_info(uint64_t start_block_index, uint64_t end_block_index)
bool hard_fork_info(uint8_t version)
bool print_peer_list_stats()
bool alt_chain_info(const std::string &tip)
bool set_validator_key(const std::string &key)
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 sign_message(const std::string privateKey, const std::string message)
bool print_transaction_pool_long()
bool generate_ed25519_keypair()
bool print_blockchain_dynamic_stats(uint64_t nblocks)
bool set_log_level(int8_t level)
bool in_peers(uint64_t limit)
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)
bool unban(const std::string &ip)
bool print_coinbase_tx_sum(uint64_t height, uint64_t count)
bool print_peer_list(bool white=true, bool gray=true, size_t limit=0)
bool pop_blocks(uint64_t num_blocks)
bool update(const std::string &command)
bool set_log_categories(const std::string &categories)
bool flush_txpool(const std::string &txid)
bool relay_tx(const std::string &txid)
bool out_peers(uint64_t limit)
bool print_block_by_hash(crypto::hash block_hash, bool include_hex)
~t_rpc_command_executor()
#define CORE_RPC_STATUS_OK
#define CORE_RPC_STATUS_BUSY
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT
#define CRYPTONOTE_PRUNING_LOG_STRIPES
#define DIFFICULTY_TARGET_V6
#define HF_VERSION_PER_BYTE_FEE
std::string message("Message requiring signing")
std::string obj_to_json_str(T &obj)
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
std::string get_time_interval_string(const time_t &time_)
type_vec_type median(std::vector< type_vec_type > &v)
const CharType(& source)[N]
unsigned __int64 uint64_t
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
uint64_t relative_out_index
std::vector< std::string > txs_hashes