| 113 | } |
| 114 | |
| 115 | static int Grind(const std::vector<std::string>& args, std::string& strPrint) |
| 116 | { |
| 117 | if (args.size() != 1) { |
| 118 | strPrint = "Must specify block header to grind"; |
| 119 | return EXIT_FAILURE; |
| 120 | } |
| 121 | |
| 122 | CBlockHeader header; |
| 123 | if (!DecodeHexBlockHeader(header, args[0])) { |
| 124 | strPrint = "Could not decode block header"; |
| 125 | return EXIT_FAILURE; |
| 126 | } |
| 127 | |
| 128 | uint32_t nBits = header.nBits; |
| 129 | std::atomic<bool> found{false}; |
| 130 | uint32_t proposed_nonce{}; |
| 131 | |
| 132 | std::vector<std::thread> threads; |
| 133 | int n_tasks = std::max(1u, std::thread::hardware_concurrency()); |
| 134 | threads.reserve(n_tasks); |
| 135 | for (int i = 0; i < n_tasks; ++i) { |
| 136 | threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found), std::ref(proposed_nonce)); |
| 137 | } |
| 138 | for (auto& t : threads) { |
| 139 | t.join(); |
| 140 | } |
| 141 | if (found) { |
| 142 | header.nNonce = proposed_nonce; |
| 143 | } else { |
| 144 | strPrint = "Could not satisfy difficulty target"; |
| 145 | return EXIT_FAILURE; |
| 146 | } |
| 147 | |
| 148 | DataStream ss{}; |
| 149 | ss << header; |
| 150 | strPrint = HexStr(ss); |
| 151 | return EXIT_SUCCESS; |
| 152 | } |
| 153 | |
| 154 | static int NetMagic(const std::vector<std::string>& args, std::string& strPrint) |
| 155 | { |
no test coverage detected