diff options
Diffstat (limited to 'src/daemon/rpc_command_executor.cpp')
-rw-r--r-- | src/daemon/rpc_command_executor.cpp | 136 |
1 files changed, 108 insertions, 28 deletions
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index ea986a398..4d3debed6 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -35,6 +35,7 @@ #include "daemon/rpc_command_executor.h" #include "rpc/core_rpc_server_commands_defs.h" #include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_basic/difficulty.h" #include "cryptonote_basic/hardfork.h" #include <boost/format.hpp> #include <ctime> @@ -65,15 +66,11 @@ namespace { time(&now); time_t last_seen = static_cast<time_t>(peer.last_seen); - std::string id_str; + std::string elapsed = epee::misc_utils::get_time_interval_string(now - last_seen); + std::string id_str = epee::string_tools::pad_string(epee::string_tools::to_string_hex(peer.id), 16, '0', true); std::string port_str; - std::string elapsed = peer.last_seen == 0 ? "never" : epee::misc_utils::get_time_interval_string(now - last_seen); - std::string ip_str = epee::string_tools::get_ip_string_from_int32(peer.ip); - std::stringstream peer_id_str; - peer_id_str << std::hex << std::setw(16) << peer.id; - peer_id_str >> id_str; epee::string_tools::xtype_to_string(peer.port, port_str); - std::string addr_str = ip_str + ":" + port_str; + std::string addr_str = peer.host + ":" + port_str; std::string rpc_port = peer.rpc_port ? std::to_string(peer.rpc_port) : "-"; std::string pruning_seed = epee::string_tools::to_string_hex(peer.pruning_seed); tools::msg_writer() << boost::format("%-10s %-25s %-25s %-5s %-4s %s") % prefix % id_str % addr_str % rpc_port % pruning_seed % elapsed; @@ -89,7 +86,7 @@ namespace { << "height: " << boost::lexical_cast<std::string>(header.height) << std::endl << "depth: " << boost::lexical_cast<std::string>(header.depth) << std::endl << "hash: " << header.hash << std::endl - << "difficulty: " << boost::lexical_cast<std::string>(header.difficulty) << std::endl + << "difficulty: " << header.wide_difficulty << std::endl << "POW hash: " << header.pow_hash << std::endl << "block size: " << header.block_size << std::endl << "block weight: " << header.block_weight << std::endl @@ -221,6 +218,9 @@ bool t_rpc_command_executor::print_peer_list_stats() { cryptonote::COMMAND_RPC_GET_PEER_LIST::response res; std::string failure_message = "Couldn't retrieve peer list"; + + req.public_only = false; + if (m_is_rpc) { if (!m_rpc_client->rpc_request(req, res, "/get_peer_list", failure_message.c_str())) @@ -350,19 +350,41 @@ bool t_rpc_command_executor::show_difficulty() { tools::success_msg_writer() << "BH: " << res.height << ", TH: " << res.top_block_hash - << ", DIFF: " << res.difficulty - << ", CUM_DIFF: " << res.cumulative_difficulty - << ", HR: " << res.difficulty / res.target << " H/s"; + << ", DIFF: " << res.wide_difficulty + << ", CUM_DIFF: " << res.wide_cumulative_difficulty + << ", HR: " << cryptonote::difficulty_type(res.wide_difficulty) / res.target << " H/s"; return true; } -static std::string get_mining_speed(uint64_t hr) +static void get_metric_prefix(cryptonote::difficulty_type hr, double& hr_d, char& prefix) +{ + if (hr < 1000) + { + prefix = 0; + return; + } + static const char metric_prefixes[4] = { 'k', 'M', 'G', 'T' }; + for (size_t i = 0; i < sizeof(metric_prefixes); ++i) + { + if (hr < 1000000) + { + hr_d = hr.convert_to<double>() / 1000; + prefix = metric_prefixes[i]; + return; + } + hr /= 1000; + } + prefix = 0; +} + +static std::string get_mining_speed(cryptonote::difficulty_type hr) { - if (hr>1e9) return (boost::format("%.2f GH/s") % (hr/1e9)).str(); - if (hr>1e6) return (boost::format("%.2f MH/s") % (hr/1e6)).str(); - if (hr>1e3) return (boost::format("%.2f kH/s") % (hr/1e3)).str(); - return (boost::format("%.0f H/s") % hr).str(); + double hr_d; + char prefix; + get_metric_prefix(hr, hr_d, prefix); + if (prefix == 0) return (boost::format("%.0f H/s") % hr).str(); + return (boost::format("%.2f %cH/s") % hr_d % prefix).str(); } static std::string get_fork_extra_info(uint64_t t, uint64_t now, uint64_t block_time) @@ -479,7 +501,7 @@ bool t_rpc_command_executor::show_status() { % (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet") % bootstrap_msg % (!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") - % get_mining_speed(ires.difficulty / ires.target) + % get_mining_speed(cryptonote::difficulty_type(ires.wide_difficulty) / ires.target) % (unsigned)hfres.version % get_fork_extra_info(hfres.earliest_height, net_height, ires.target) % (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked") @@ -742,7 +764,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u << ", size: " << header.block_size << ", weight: " << header.block_weight << " (long term " << header.long_term_weight << "), transactions: " << header.num_txes << std::endl << "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl << "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl - << "difficulty: " << header.difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl; + << "difficulty: " << header.wide_difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl; first = false; } @@ -1818,7 +1840,7 @@ bool t_rpc_command_executor::print_coinbase_tx_sum(uint64_t height, uint64_t cou return true; } -bool t_rpc_command_executor::alt_chain_info(const std::string &tip) +bool t_rpc_command_executor::alt_chain_info(const std::string &tip, size_t above, uint64_t last_blocks) { cryptonote::COMMAND_RPC_GET_INFO::request ireq; cryptonote::COMMAND_RPC_GET_INFO::response ires; @@ -1855,16 +1877,31 @@ bool t_rpc_command_executor::alt_chain_info(const std::string &tip) if (tip.empty()) { - tools::msg_writer() << boost::lexical_cast<std::string>(res.chains.size()) << " alternate chains found:"; - for (const auto &chain: res.chains) + auto chains = res.chains; + std::sort(chains.begin(), chains.end(), [](const cryptonote::COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info &info0, cryptonote::COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info &info1){ return info0.height < info1.height; }); + std::vector<size_t> display; + for (size_t i = 0; i < chains.size(); ++i) { - uint64_t start_height = (chain.height - chain.length + 1); + const auto &chain = chains[i]; + if (chain.length <= above) + continue; + const uint64_t start_height = (chain.height - chain.length + 1); + if (last_blocks > 0 && ires.height - 1 - start_height >= last_blocks) + continue; + display.push_back(i); + } + tools::msg_writer() << boost::lexical_cast<std::string>(display.size()) << " alternate chains found:"; + for (const size_t idx: display) + { + const auto &chain = chains[idx]; + const uint64_t start_height = (chain.height - chain.length + 1); tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1) - << " deep), diff " << chain.difficulty << ": " << chain.block_hash; + << " deep), diff " << chain.wide_difficulty << ": " << chain.block_hash; } } else { + const uint64_t now = time(NULL); const auto i = std::find_if(res.chains.begin(), res.chains.end(), [&tip](cryptonote::COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info &info){ return info.block_hash == tip; }); if (i != res.chains.end()) { @@ -1872,10 +1909,53 @@ bool t_rpc_command_executor::alt_chain_info(const std::string &tip) tools::success_msg_writer() << "Found alternate chain with tip " << tip; uint64_t start_height = (chain.height - chain.length + 1); tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1) - << " deep), diff " << chain.difficulty << ":"; + << " deep), diff " << chain.wide_difficulty << ":"; for (const std::string &block_id: chain.block_hashes) tools::msg_writer() << " " << block_id; tools::msg_writer() << "Chain parent on main chain: " << chain.main_chain_parent_block; + cryptonote::COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request bhreq; + cryptonote::COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response bhres; + bhreq.hashes = chain.block_hashes; + bhreq.hashes.push_back(chain.main_chain_parent_block); + bhreq.fill_pow_hash = false; + if (m_is_rpc) + { + if (!m_rpc_client->json_rpc_request(bhreq, bhres, "getblockheaderbyhash", fail_message.c_str())) + { + return true; + } + } + else + { + if (!m_rpc_server->on_get_block_header_by_hash(bhreq, bhres, error_resp)) + { + tools::fail_msg_writer() << make_error(fail_message, res.status); + return true; + } + } + if (bhres.block_headers.size() != chain.length + 1) + { + tools::fail_msg_writer() << "Failed to get block header info for alt chain"; + return true; + } + uint64_t t0 = bhres.block_headers.front().timestamp, t1 = t0; + for (const cryptonote::block_header_response &block_header: bhres.block_headers) + { + t0 = std::min<uint64_t>(t0, block_header.timestamp); + t1 = std::max<uint64_t>(t1, block_header.timestamp); + } + const uint64_t dt = t1 - t0; + const uint64_t age = std::max(dt, t0 < now ? now - t0 : 0); + tools::msg_writer() << "Age: " << tools::get_human_readable_timespan(age); + if (chain.length > 1) + { + tools::msg_writer() << "Time span: " << tools::get_human_readable_timespan(dt); + cryptonote::difficulty_type start_difficulty = bhres.block_headers.back().difficulty; + if (start_difficulty > 0) + tools::msg_writer() << "Approximated " << 100.f * DIFFICULTY_TARGET_V2 * chain.length / dt << "% of network hash rate"; + else + tools::fail_msg_writer() << "Bad cmumulative difficulty reported by dameon"; + } } else tools::fail_msg_writer() << "Block hash " << tip << " is not the tip of any known alternate chain"; @@ -1933,7 +2013,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) } } - tools::msg_writer() << "Height: " << ires.height << ", diff " << ires.difficulty << ", cum. diff " << ires.cumulative_difficulty + tools::msg_writer() << "Height: " << ires.height << ", diff " << ires.wide_difficulty << ", cum. diff " << ires.wide_cumulative_difficulty << ", target " << ires.target << " sec" << ", dyn fee " << cryptonote::print_money(feres.fee) << "/" << (hfres.enabled ? "byte" : "kB"); if (nblocks > 0) @@ -1960,7 +2040,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) } } - double avgdiff = 0; + cryptonote::difficulty_type avgdiff = 0; double avgnumtxes = 0; double avgreward = 0; std::vector<uint64_t> weights; @@ -1969,7 +2049,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) std::vector<unsigned> major_versions(256, 0), minor_versions(256, 0); for (const auto &bhr: bhres.headers) { - avgdiff += bhr.difficulty; + avgdiff += cryptonote::difficulty_type(bhr.wide_difficulty); avgnumtxes += bhr.num_txes; avgreward += bhr.reward; weights.push_back(bhr.block_weight); @@ -1984,7 +2064,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) avgnumtxes /= nblocks; avgreward /= nblocks; uint64_t median_block_weight = epee::misc_utils::median(weights); - tools::msg_writer() << "Last " << nblocks << ": avg. diff " << (uint64_t)avgdiff << ", " << (latest - earliest) / nblocks << " avg sec/block, avg num txes " << avgnumtxes + tools::msg_writer() << "Last " << nblocks << ": avg. diff " << avgdiff << ", " << (latest - earliest) / nblocks << " avg sec/block, avg num txes " << avgnumtxes << ", avg. reward " << cryptonote::print_money(avgreward) << ", median block weight " << median_block_weight; unsigned int max_major = 256, max_minor = 256; |