//----------------------------------------------------------------------------------------------------- bool miner::find_nonce_for_given_block(crypto::cn_context &context, Block& bl, const difficulty_type& diffic) { unsigned nthreads = std::thread::hardware_concurrency(); if (nthreads > 0 && diffic > 5) { std::vector<std::future<void>> threads(nthreads); std::atomic<uint32_t> foundNonce; std::atomic<bool> found(false); uint32_t startNonce = crypto::rand<uint32_t>(); for (unsigned i = 0; i < nthreads; ++i) { threads[i] = std::async(std::launch::async, [&, i]() { crypto::cn_context localctx; crypto::hash h; Block lb(bl); // copy to local block for (uint32_t nonce = startNonce + i; !found; nonce += nthreads) { lb.nonce = nonce; if (!get_block_longhash(localctx, lb, h)) { return; } if (check_hash(h, diffic)) { foundNonce = nonce; found = true; return; } } }); } for (auto& t : threads) { t.wait(); } if (found) { bl.nonce = foundNonce.load(); } return found; } else { for (; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++) { crypto::hash h; if (!get_block_longhash(context, bl, h)) { return false; } if (check_hash(h, diffic)) { return true; } } } return false; }
bool Currency::checkProofOfWork(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, crypto::hash& proofOfWork) const { if (!get_block_longhash(context, block, proofOfWork)) { return false; } return check_hash(proofOfWork, currentDiffic); }
void Miner::workerFunc(const Block& blockTemplate, difficulty_type difficulty, uint32_t nonceStep) { try { Block block = blockTemplate; Crypto::cn_context cryptoContext; while (m_state == MiningState::MINING_IN_PROGRESS) { Crypto::Hash hash; if (!get_block_longhash(cryptoContext, block, hash)) { //error occured m_logger(Logging::DEBUGGING) << "calculating long hash error occured"; m_state = MiningState::MINING_STOPPED; return; } if (check_hash(hash, difficulty)) { m_logger(Logging::INFO) << "Found block for difficulty " << difficulty; if (!setStateBlockFound()) { m_logger(Logging::DEBUGGING) << "block is already found or mining stopped"; return; } m_block = block; return; } block.nonce += nonceStep; } } catch (std::exception& e) { m_logger(Logging::ERROR) << "Miner got error: " << e.what(); m_state = MiningState::MINING_STOPPED; } }
crypto::hash findBlockNonce(cryptonote::block& block, uint8_t* long_state) { crypto::hash blockHash = cryptonote::null_hash; while (!m_nonceFound && !m_stopped) { crypto::hash hash; bool result = get_block_longhash(block, hash, m_height, long_state); ++m_hashes; if (!result) { break; } if (cryptonote::check_hash(hash, m_difficulty)) { m_nonce = block.nonce; m_nonceFound = true; blockHash = hash; break; } if (std::numeric_limits<uint32_t>::max() - block.nonce < m_threads) { break; } block.nonce += static_cast<uint32_t>(m_threads); } return blockHash; }
//----------------------------------------------------------------------------------------------------- bool miner::worker_thread(uint32_t th_local_index) { logger(INFO) << "Miner thread was started ["<< th_local_index << "]"; uint32_t nonce = m_starter_nonce + th_local_index; difficulty_type local_diff = 0; uint32_t local_template_ver = 0; crypto::cn_context context; Block b; while(!m_stop) { if(m_pausers_count) //anti split workaround { std::this_thread::sleep_for(std::chrono::milliseconds(100)); continue; } if(local_template_ver != m_template_no) { std::unique_lock<std::mutex> lk(m_template_lock); b = m_template; local_diff = m_diffic; lk.unlock(); local_template_ver = m_template_no; nonce = m_starter_nonce + th_local_index; } if(!local_template_ver)//no any set_block_template call { logger(TRACE) << "Block template not set yet"; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); continue; } b.nonce = nonce; crypto::hash h; if (!m_stop && !get_block_longhash(context, b, h)) { logger(ERROR) << "Failed to get block long hash"; m_stop = true; } if (!m_stop && check_hash(h, local_diff)) { //we lucky! ++m_config.current_extra_message_index; logger(INFO, GREEN) << "Found block for difficulty: " << local_diff; if(!m_handler.handle_block_found(b)) { --m_config.current_extra_message_index; } else { //success update, lets update config Common::saveStringToFile(m_config_folder_path + "/" + CryptoNote::parameters::MINER_CONFIG_FILE_NAME, storeToJson(m_config)); } } nonce += m_threads_total; ++m_hashes; } logger(INFO) << "Miner thread stopped ["<< th_local_index << "]"; return true; }