diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 3d540e7..dcf742c 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -669,6 +669,7 @@ namespace cryptonote { crypto::public_key m_spend_public_key; crypto::public_key m_view_public_key; + bool m_is_carrot; BEGIN_SERIALIZE_OBJECT() FIELD(m_spend_public_key) @@ -683,7 +684,8 @@ namespace cryptonote bool operator==(const account_public_address& rhs) const { return m_spend_public_key == rhs.m_spend_public_key && - m_view_public_key == rhs.m_view_public_key; + m_view_public_key == rhs.m_view_public_key && + m_is_carrot == rhs.m_is_carrot; } bool operator!=(const account_public_address& rhs) const diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index b7ebcf0..bfa041c 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -285,6 +285,8 @@ namespace cryptonote { LOG_PRINT_L1("Failed to validate address keys"); return false; } + + info.address.m_is_carrot = info.is_carrot; } else { @@ -316,6 +318,7 @@ namespace cryptonote { //we success info.address = blob.m_address; + info.address.m_is_carrot = false; info.is_subaddress = false; info.has_payment_id = false; info.is_carrot = false; diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 3161dc3..9183237 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -176,6 +176,7 @@ namespace cryptonote if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce, seed_height, seed_hash)) { LOG_ERROR("Failed to get_block_template(), stopping mining"); + stop(); return false; } set_block_template(bl, di, height, expected_reward); @@ -185,7 +186,12 @@ namespace cryptonote bool miner::on_idle() { m_update_block_template_interval.do_call([&](){ - if(is_mining())request_block_template(); + if(is_mining()) { + if (!request_block_template()) { + stop(); + return false; + } + } return true; }); @@ -393,7 +399,10 @@ namespace cryptonote return false; } - request_block_template();//lets update block template + if (!request_block_template()) { + LOG_ERROR("Unable to start miner - unknown error"); + return false; + } m_stop = false; m_thread_index = 0; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 5ced780..382b238 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1866,6 +1866,15 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, b.timestamp = median_ts; } + // Verify that we aren't mixing Carrot and non-Carrot + if (b.major_version >= HF_VERSION_CARROT && !miner_address.m_is_carrot) { + LOG_ERROR("mining to CryptoNote wallet address, but Carrot wallet address is required"); + return false; + } else if (b.major_version < HF_VERSION_CARROT && miner_address.m_is_carrot) { + LOG_ERROR("mining to Carrot wallet address, but Carrot isn't supported yet"); + return false; + } + std::map circ_supply = get_db().get_circulating_supply(); // Check if we are supposed to be obtaining PRs from the Oracle @@ -2355,7 +2364,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id if(!prevalidate_protocol_transaction(b, bei.height, hf_version)) { - MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction."); + MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect protocol transaction."); bvc.m_verifivation_failed = true; return false; } diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 998db90..91fd80d 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -374,6 +374,8 @@ bool t_command_parser_executor::start_mining(const std::vector& arg return true; } + bool is_carrot = m_executor.current_hard_fork_version() >= HF_VERSION_CARROT; + cryptonote::address_parse_info info; cryptonote::network_type nettype = cryptonote::MAINNET; if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, args.front())) @@ -420,6 +422,13 @@ bool t_command_parser_executor::start_mining(const std::vector& arg tools::fail_msg_writer() << "subaddress for mining reward is not yet supported!" << std::endl; return true; } + if (info.is_carrot && !is_carrot) { + tools::fail_msg_writer() << "mining to Carrot wallet address, but Carrot isn't supported yet" << std::endl; + return true; + } else if (!info.is_carrot && is_carrot) { + tools::fail_msg_writer() << "mining to CryptoNote wallet address, but Carrot wallet address is required" << std::endl; + return true; + } if(nettype != cryptonote::MAINNET) std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << " address, make sure this is intentional!" << std::endl; uint64_t threads_count = 1; @@ -470,7 +479,7 @@ bool t_command_parser_executor::start_mining(const std::vector& arg } } - m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery); + m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery, info.is_carrot); return true; } diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index b5bd579..6c8eb01 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -1352,10 +1352,10 @@ bool t_rpc_command_executor::print_transaction_pool_stats() { return true; } -bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery) { +bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery, bool is_carrot) { cryptonote::COMMAND_RPC_START_MINING::request req; cryptonote::COMMAND_RPC_START_MINING::response res; - req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address); + req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address, is_carrot); req.threads_count = num_threads; req.do_background_mining = do_background_mining; req.ignore_battery = ignore_battery; @@ -1650,6 +1650,34 @@ bool t_rpc_command_executor::in_peers(bool set, uint32_t limit) return true; } +uint8_t t_rpc_command_executor::current_hard_fork_version() +{ + cryptonote::COMMAND_RPC_HARD_FORK_INFO::request req; + cryptonote::COMMAND_RPC_HARD_FORK_INFO::response res; + std::string fail_message = "Unsuccessful"; + epee::json_rpc::error error_resp; + + req.version = 0; + + if (m_is_rpc) + { + if (!m_rpc_client->json_rpc_request(req, res, "hard_fork_info", fail_message.c_str())) + { + return 0; + } + } + else + { + if (!m_rpc_server->on_hard_fork_info(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) + { + tools::fail_msg_writer() << make_error(fail_message, res.status); + return 0; + } + } + + return res.version; +} + bool t_rpc_command_executor::hard_fork_info(uint8_t version) { cryptonote::COMMAND_RPC_HARD_FORK_INFO::request req; diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index ebd7eda..e6920bf 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -106,7 +106,7 @@ public: bool print_transaction_pool_stats(); - 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 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 is_carrot = false); bool stop_mining(); @@ -128,6 +128,8 @@ public: bool in_peers(bool set, uint32_t limit); + uint8_t current_hard_fork_version(); + bool hard_fork_info(uint8_t version); bool print_bans(); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 52c32dd..d5764bd 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1432,7 +1432,7 @@ namespace cryptonote RPC_TRACKER(start_mining); CHECK_CORE_READY(); cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, nettype(), req.miner_address)) + if(!get_account_address_from_str(info, m_core.get_nettype(), req.miner_address)) { res.status = "Failed, wrong address"; LOG_PRINT_L0(res.status); @@ -1445,6 +1445,17 @@ namespace cryptonote return true; } + const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version(); + if (info.is_carrot && version < HF_VERSION_CARROT) { + res.status = "Mining to Carrot wallet address, but Carrot isn't supported yet"; + LOG_PRINT_L0(res.status); + return true; + } else if (!info.is_carrot && version >= HF_VERSION_CARROT) { + res.status = "Mining to CryptoNote wallet address, but Carrot wallet address is required"; + LOG_PRINT_L0(res.status); + return true; + } + unsigned int concurrency_count = boost::thread::hardware_concurrency() * 4; // if we couldn't detect threads, set it to a ridiculously high number @@ -1958,6 +1969,17 @@ namespace cryptonote return false; } + const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version(); + if (info.is_carrot && version < HF_VERSION_CARROT) { + error_resp.code = CORE_RPC_ERROR_CODE_INVALID_CLIENT; + error_resp.message = "Mining to Carrot wallet address, but Carrot isn't supported yet"; + return false; + } else if (!info.is_carrot && version >= HF_VERSION_CARROT) { + error_resp.code = CORE_RPC_ERROR_CODE_INVALID_CLIENT; + error_resp.message = "Mining to CryptoNote wallet address, but Carrot wallet address is required"; + return false; + } + block b; cryptonote::blobdata blob_reserve; size_t reserved_offset;