diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 7fc720f8a..6628c8448 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -119,7 +119,8 @@ namespace cryptonote m_min_idle_seconds(BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS), m_idle_threshold(BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE), m_mining_target(BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE), - m_miner_extra_sleep(BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS) + m_miner_extra_sleep(BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS), + m_block_reward(0) { } @@ -130,12 +131,13 @@ namespace cryptonote catch (...) { /* ignore */ } } //----------------------------------------------------------------------------------------------------- - bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height) + bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height, uint64_t block_reward) { CRITICAL_REGION_LOCAL(m_template_lock); m_template = bl; m_diffic = di; m_height = height; + m_block_reward = block_reward; ++m_template_no; m_starter_nonce = crypto::rand(); return true; @@ -167,7 +169,7 @@ namespace cryptonote LOG_ERROR("Failed to get_block_template(), stopping mining"); return false; } - set_block_template(bl, di, height); + set_block_template(bl, di, height, expected_reward); return true; } //----------------------------------------------------------------------------------------------------- @@ -359,6 +361,7 @@ namespace cryptonote //----------------------------------------------------------------------------------------------------- bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background, bool ignore_battery) { + m_block_reward = 0; m_mine_address = adr; m_threads_total = static_cast(threads_count); if (threads_count == 0) diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index e608d7083..08b1bd7f1 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -61,7 +61,7 @@ namespace cryptonote ~miner(); bool init(const boost::program_options::variables_map& vm, network_type nettype); static void init_options(boost::program_options::options_description& desc); - bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height); + bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height, uint64_t block_reward); bool on_block_chain_update(); bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background = false, bool ignore_battery = false); uint64_t get_speed() const; @@ -85,6 +85,7 @@ namespace cryptonote bool set_idle_threshold(uint8_t idle_threshold); uint8_t get_mining_target() const; bool set_mining_target(uint8_t mining_target); + uint64_t get_block_reward() const { return m_block_reward; } static constexpr uint8_t BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE = 90; static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 50; @@ -169,5 +170,6 @@ namespace cryptonote static bool get_process_time(uint64_t& total_time); static uint8_t get_percent_of_total(uint64_t some_time, uint64_t total_time); static boost::logic::tribool on_battery_power(); + std::atomic m_block_reward; }; } diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index ba8ab9609..b324ab99d 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -411,6 +411,11 @@ bool t_command_parser_executor::stop_mining(const std::vector& args return m_executor.stop_mining(); } +bool t_command_parser_executor::mining_status(const std::vector& args) +{ + return m_executor.mining_status(); +} + bool t_command_parser_executor::stop_daemon(const std::vector& args) { if (!args.empty()) return false; diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h index ca5cc8947..bec6e4522 100644 --- a/src/daemon/command_parser_executor.h +++ b/src/daemon/command_parser_executor.h @@ -97,6 +97,8 @@ public: bool stop_mining(const std::vector& args); + bool mining_status(const std::vector& args); + bool stop_daemon(const std::vector& args); bool print_status(const std::vector& args); diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index e986d4d95..94e4a8bf1 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -112,6 +112,11 @@ t_command_server::t_command_server( , std::bind(&t_command_parser_executor::stop_mining, &m_parser, p::_1) , "Stop mining." ); + m_command_lookup.set_handler( + "mining_status" + , std::bind(&t_command_parser_executor::mining_status, &m_parser, p::_1) + , "Show current mining status." + ); m_command_lookup.set_handler( "print_pool" , std::bind(&t_command_parser_executor::print_transaction_pool_long, &m_parser, p::_1) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 0e692f2c8..8aaf9ba66 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -462,7 +462,7 @@ bool t_rpc_command_executor::show_status() { % get_sync_percentage(ires) % (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) + std::string(" to ") + mres.address ) : "not mining") + % (!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) % (unsigned)hfres.version % get_fork_extra_info(hfres.earliest_height, net_height, ires.target) @@ -487,6 +487,81 @@ bool t_rpc_command_executor::show_status() { return true; } +bool t_rpc_command_executor::mining_status() { + cryptonote::COMMAND_RPC_MINING_STATUS::request mreq; + cryptonote::COMMAND_RPC_MINING_STATUS::response mres; + epee::json_rpc::error error_resp; + bool has_mining_info = true; + + std::string fail_message = "Problem fetching info"; + + bool mining_busy = false; + if (m_is_rpc) + { + // mining info is only available non unrestricted RPC mode + has_mining_info = m_rpc_client->rpc_request(mreq, mres, "/mining_status", fail_message.c_str()); + } + else + { + if (!m_rpc_server->on_mining_status(mreq, mres)) + { + tools::fail_msg_writer() << fail_message.c_str(); + return true; + } + + if (mres.status == CORE_RPC_STATUS_BUSY) + { + mining_busy = true; + } + else if (mres.status != CORE_RPC_STATUS_OK) + { + tools::fail_msg_writer() << make_error(fail_message, mres.status); + return true; + } + } + + if (!has_mining_info) + { + tools::fail_msg_writer() << "Mining info unavailable"; + return true; + } + + if (mining_busy || !mres.active) + { + tools::msg_writer() << "Not currently mining"; + } + else + { + tools::msg_writer() << "Mining at " << get_mining_speed(mres.speed) << " with " << mres.threads_count << " threads"; + } + + if (mres.active || mres.is_background_mining_enabled) + { + tools::msg_writer() << "PoW algorithm: " << mres.pow_algorithm; + tools::msg_writer() << "Mining address: " << mres.address; + } + + if (mres.is_background_mining_enabled) + { + tools::msg_writer() << "Smart mining enabled:"; + tools::msg_writer() << " Target: " << (unsigned)mres.bg_target << "% CPU"; + tools::msg_writer() << " Idle threshold: " << (unsigned)mres.bg_idle_threshold << "% CPU"; + tools::msg_writer() << " Min idle time: " << (unsigned)mres.bg_min_idle_seconds << " seconds"; + tools::msg_writer() << " Ignore battery: " << (mres.bg_ignore_battery ? "yes" : "no"); + } + + if (!mining_busy && mres.active) + { + uint64_t daily = 86400ull / mres.block_target * mres.block_reward; + uint64_t monthly = 86400ull / mres.block_target * 30.5 * mres.block_reward; + uint64_t yearly = 86400ull / mres.block_target * 356 * mres.block_reward; + tools::msg_writer() << "Expected: " << cryptonote::print_money(daily) << " monero daily, " + << cryptonote::print_money(monthly) << " monero monthly, " << cryptonote::print_money(yearly) << " yearly"; + } + + return true; +} + bool t_rpc_command_executor::print_connections() { cryptonote::COMMAND_RPC_GET_CONNECTIONS::request req; cryptonote::COMMAND_RPC_GET_CONNECTIONS::response res; diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index 503c403f7..423132b79 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -109,6 +109,8 @@ public: bool stop_mining(); + bool mining_status(); + bool stop_daemon(); bool print_status(); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index ecb8fc2c8..6357f84b1 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -915,11 +915,30 @@ namespace cryptonote res.active = lMiner.is_mining(); res.is_background_mining_enabled = lMiner.get_is_background_mining_enabled(); + res.block_target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; if ( lMiner.is_mining() ) { res.speed = lMiner.get_speed(); res.threads_count = lMiner.get_threads_count(); - const account_public_address& lMiningAdr = lMiner.get_mining_address(); - res.address = get_account_address_as_str(nettype(), false, lMiningAdr); + res.block_reward = lMiner.get_block_reward(); + } + const account_public_address& lMiningAdr = lMiner.get_mining_address(); + res.address = get_account_address_as_str(nettype(), false, lMiningAdr); + const uint8_t major_version = m_core.get_blockchain_storage().get_current_hard_fork_version(); + const unsigned variant = major_version >= 7 ? major_version - 6 : 0; + switch (variant) + { + case 0: res.pow_algorithm = "Cryptonight"; break; + case 1: res.pow_algorithm = "CNv1 (Cryptonight variant 1)"; break; + case 2: case 3: res.pow_algorithm = "CNv2 (Cryptonight variant 2)"; break; + case 4: case 5: res.pow_algorithm = "CNv4 (Cryptonight variant 4)"; break; + default: res.pow_algorithm = "I'm not sure actually"; break; + } + if (res.is_background_mining_enabled) + { + res.bg_idle_threshold = lMiner.get_idle_threshold(); + res.bg_min_idle_seconds = lMiner.get_min_idle_seconds(); + res.bg_ignore_battery = lMiner.get_ignore_battery(); + res.bg_target = lMiner.get_mining_target(); } res.status = CORE_RPC_STATUS_OK; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 4204e818f..7ee25ca85 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1055,7 +1055,14 @@ namespace cryptonote uint64_t speed; uint32_t threads_count; std::string address; + std::string pow_algorithm; bool is_background_mining_enabled; + uint8_t bg_idle_threshold; + uint8_t bg_min_idle_seconds; + bool bg_ignore_battery; + uint8_t bg_target; + uint32_t block_target; + uint64_t block_reward; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) @@ -1063,7 +1070,14 @@ namespace cryptonote KV_SERIALIZE(speed) KV_SERIALIZE(threads_count) KV_SERIALIZE(address) + KV_SERIALIZE(pow_algorithm) KV_SERIALIZE(is_background_mining_enabled) + KV_SERIALIZE(bg_idle_threshold) + KV_SERIALIZE(bg_min_idle_seconds) + KV_SERIALIZE(bg_ignore_battery) + KV_SERIALIZE(bg_target) + KV_SERIALIZE(block_target) + KV_SERIALIZE(block_reward) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init response;