| 109 | } |
| 110 | |
| 111 | static int Grind(const std::vector<std::string>& args, std::string& strPrint) |
| 112 | { |
| 113 | if (args.size() != 1) { |
| 114 | strPrint = "Must specify block header to grind"; |
| 115 | return EXIT_FAILURE; |
| 116 | } |
| 117 | |
| 118 | CBlockHeader header; |
| 119 | if (!DecodeHexBlockHeader(header, args[0])) { |
| 120 | strPrint = "Could not decode block header"; |
| 121 | return EXIT_FAILURE; |
| 122 | } |
| 123 | |
| 124 | uint32_t nBits = header.nBits; |
| 125 | std::atomic<bool> found{false}; |
| 126 | |
| 127 | std::vector<std::thread> threads; |
| 128 | int n_tasks = std::max(1u, std::thread::hardware_concurrency()); |
| 129 | for (int i = 0; i < n_tasks; ++i) { |
| 130 | threads.emplace_back( grind_task, nBits, std::ref(header), i, n_tasks, std::ref(found) ); |
| 131 | } |
| 132 | for (auto& t : threads) { |
| 133 | t.join(); |
| 134 | } |
| 135 | if (!found) { |
| 136 | strPrint = "Could not satisfy difficulty target"; |
| 137 | return EXIT_FAILURE; |
| 138 | } |
| 139 | |
| 140 | CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); |
| 141 | ss << header; |
| 142 | strPrint = HexStr(ss); |
| 143 | return EXIT_SUCCESS; |
| 144 | } |
| 145 | |
| 146 | #ifdef WIN32 |
| 147 | // Export main() and ensure working ASLR on Windows. |
no test coverage detected