LCOV - code coverage report
Current view: top level - src - bitcoin-util.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 47 109 43.1 %
Date: 2026-06-25 07:23:51 Functions: 5 6 83.3 %

          Line data    Source code
       1             : // Copyright (c) 2009-2020 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #if defined(HAVE_CONFIG_H)
       6             : #include <config/bitcoin-config.h>
       7             : #endif
       8             : 
       9             : #include <arith_uint256.h>
      10             : #include <chain.h>
      11             : #include <chainparams.h>
      12             : #include <chainparamsbase.h>
      13             : #include <clientversion.h>
      14             : #include <core_io.h>
      15             : #include <streams.h>
      16             : #include <util/system.h>
      17             : #include <util/translation.h>
      18             : 
      19             : #include <atomic>
      20             : #include <cstdio>
      21             : #include <functional>
      22             : #include <memory>
      23             : #include <thread>
      24             : 
      25             : static const int CONTINUE_EXECUTION=-1;
      26             : 
      27           5 : const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
      28             : 
      29           5 : static void SetupBitcoinUtilArgs(ArgsManager &argsman)
      30             : {
      31           5 :     SetupHelpOptions(argsman);
      32             : 
      33           5 :     argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
      34             : 
      35           5 :     argsman.AddCommand("grind", "Perform proof of work on hex header string");
      36             : 
      37           5 :     SetupChainParamsBaseOptions(argsman);
      38           5 : }
      39             : 
      40             : // This function returns either one of EXIT_ codes when it's expected to stop the process or
      41             : // CONTINUE_EXECUTION when it's expected to continue further.
      42           5 : static int AppInitUtil(ArgsManager& args, int argc, char* argv[])
      43             : {
      44           5 :     SetupBitcoinUtilArgs(args);
      45           5 :     std::string error;
      46           5 :     if (!args.ParseParameters(argc, argv, error)) {
      47           2 :         tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
      48           2 :         return EXIT_FAILURE;
      49             :     }
      50             : 
      51           3 :     if (HelpRequested(args) || args.IsArgSet("-version")) {
      52             :         // First part of help message is specific to this utility
      53           0 :         std::string strUsage = PACKAGE_NAME " dash-util utility version " + FormatFullVersion() + "\n";
      54           0 :         if (args.IsArgSet("-version")) {
      55           0 :             strUsage += FormatParagraph(LicenseInfo());
      56           0 :         } else {
      57           0 :             strUsage += "\n"
      58             :                 "Usage:  dash-util [options] [commands]  Do stuff\n";
      59           0 :             strUsage += "\n" + args.GetHelpMessage();
      60             :         }
      61             : 
      62           0 :         tfm::format(std::cout, "%s", strUsage);
      63             : 
      64           0 :         if (argc < 2) {
      65           0 :             tfm::format(std::cerr, "Error: too few parameters\n");
      66           0 :             return EXIT_FAILURE;
      67             :         }
      68           0 :         return EXIT_SUCCESS;
      69           0 :     }
      70             : 
      71             :     // Check for chain settings (Params() calls are only valid after this clause)
      72             :     try {
      73           3 :         SelectParams(args.GetChainName());
      74           3 :     } catch (const std::exception& e) {
      75           0 :         tfm::format(std::cerr, "Error: %s\n", e.what());
      76           0 :         return EXIT_FAILURE;
      77           0 :     }
      78             : 
      79           3 :     return CONTINUE_EXECUTION;
      80           5 : }
      81             : 
      82           0 : static void grind_task(uint32_t nBits, CBlockHeader header, uint32_t offset, uint32_t step, std::atomic<bool>& found, uint32_t& proposed_nonce)
      83             : {
      84           0 :     arith_uint256 target;
      85             :     bool neg, over;
      86           0 :     target.SetCompact(nBits, &neg, &over);
      87           0 :     if (target == 0 || neg || over) return;
      88           0 :     header.nNonce = offset;
      89             : 
      90           0 :     uint32_t finish = std::numeric_limits<uint32_t>::max() - step;
      91           0 :     finish = finish - (finish % step) + offset;
      92             : 
      93           0 :     while (!found && header.nNonce < finish) {
      94           0 :         const uint32_t next = (finish - header.nNonce < 5000*step) ? finish : header.nNonce + 5000*step;
      95           0 :         do {
      96           0 :             if (UintToArith256(header.GetHash()) <= target) {
      97           0 :                 if (!found.exchange(true)) {
      98           0 :                     proposed_nonce = header.nNonce;
      99           0 :                 }
     100           0 :                 return;
     101             :             }
     102           0 :             header.nNonce += step;
     103           0 :         } while(header.nNonce != next);
     104             :     }
     105           0 : }
     106             : 
     107           3 : static int Grind(const std::vector<std::string>& args, std::string& strPrint)
     108             : {
     109           3 :     if (args.size() != 1) {
     110           2 :         strPrint = "Must specify block header to grind";
     111           2 :         return EXIT_FAILURE;
     112             :     }
     113             : 
     114           1 :     CBlockHeader header;
     115           1 :     if (!DecodeHexBlockHeader(header, args[0])) {
     116           1 :         strPrint = "Could not decode block header";
     117           1 :         return EXIT_FAILURE;
     118             :     }
     119             : 
     120           0 :     uint32_t nBits = header.nBits;
     121           0 :     std::atomic<bool> found{false};
     122           0 :     uint32_t proposed_nonce{};
     123             : 
     124           0 :     std::vector<std::thread> threads;
     125           0 :     int n_tasks = std::max(1u, std::thread::hardware_concurrency());
     126           0 :     for (int i = 0; i < n_tasks; ++i) {
     127           0 :         threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found), std::ref(proposed_nonce));
     128           0 :     }
     129           0 :     for (auto& t : threads) {
     130           0 :         t.join();
     131             :     }
     132           0 :     if (found) {
     133           0 :         header.nNonce = proposed_nonce;
     134           0 :     } else {
     135           0 :         strPrint = "Could not satisfy difficulty target";
     136           0 :         return EXIT_FAILURE;
     137             :     }
     138             : 
     139           0 :     DataStream ss{};
     140           0 :     ss << header;
     141           0 :     strPrint = HexStr(ss);
     142           0 :     return EXIT_SUCCESS;
     143           3 : }
     144             : 
     145             : #ifdef WIN32
     146             : // Export main() and ensure working ASLR on Windows.
     147             : // Exporting a symbol will prevent the linker from stripping
     148             : // the .reloc section from the binary, which is a requirement
     149             : // for ASLR. This is a temporary workaround until a fixed
     150             : // version of binutils is used for releases.
     151             : __declspec(dllexport) int main(int argc, char* argv[])
     152             : #else
     153           5 : int main(int argc, char* argv[])
     154             : #endif
     155             : {
     156           5 :     ArgsManager& args = gArgs;
     157           5 :     SetupEnvironment();
     158             : 
     159             :     try {
     160           5 :         int ret = AppInitUtil(args, argc, argv);
     161           5 :         if (ret != CONTINUE_EXECUTION) {
     162           2 :             return ret;
     163             :         }
     164           3 :     } catch (...) {
     165           0 :         PrintExceptionContinue(std::current_exception(), "AppInitUtil()");
     166           0 :         return EXIT_FAILURE;
     167           0 :     }
     168             : 
     169           3 :     const auto cmd = args.GetCommand();
     170           3 :     if (!cmd) {
     171           0 :         tfm::format(std::cerr, "Error: must specify a command\n");
     172           0 :         return EXIT_FAILURE;
     173             :     }
     174             : 
     175           3 :     int ret = EXIT_FAILURE;
     176           3 :     std::string strPrint;
     177             :     try {
     178           3 :         if (cmd->command == "grind") {
     179           3 :             ret = Grind(cmd->args, strPrint);
     180           3 :         } else {
     181           0 :             assert(false); // unknown command should be caught earlier
     182             :         }
     183           3 :     } catch (const std::exception& e) {
     184           0 :         strPrint = std::string("error: ") + e.what();
     185           0 :     } catch (...) {
     186           0 :         strPrint = "unknown error";
     187           0 :     }
     188             : 
     189           3 :     if (strPrint != "") {
     190           3 :         tfm::format(ret == 0 ? std::cout : std::cerr, "%s\n", strPrint);
     191           3 :     }
     192             : 
     193           3 :     return ret;
     194           5 : }

Generated by: LCOV version 1.16