Merge bitcoin/bitcoin#26120: refactor: Make bitcoin-util grind_task tsan friendly

fafcc94398 Make bitcoin-util grind_task tsan friendly (MacroFake)

Pull request description:

  While there is no issue with the current code, `libtsan-12.2.1` on my machine does not seem to like it. This is understandable, because the nonce isn't protected by a mutex that the sanitizer can see (only by an atomic, which achieves the same).

  Fix this by guarding the nonce by the existing atomic bool, which tsan seems to understand.

ACKs for top commit:
  ajtowns:
    ACK fafcc94398
  hebasto:
    ACK fafcc94398, I have reviewed the code and it looks OK, I agree it can be merged. Confirming that initial bug has been fixed.

Tree-SHA512: 4e67fab5833ec7d91678b85a300368892ee9f7cd89a52cc5e15a7df65b2da813b24eaffd8362d0d8a3c8951e024041d69ebddf25101b11d0a1a62c1208ddc9a5
This commit is contained in:
MarcoFalke 2022-12-17 11:46:07 +01:00
commit caa2240680
No known key found for this signature in database
GPG Key ID: CE2B75697E69A548

View File

@ -82,13 +82,12 @@ static int AppInitUtil(ArgsManager& args, int argc, char* argv[])
return CONTINUE_EXECUTION;
}
static void grind_task(uint32_t nBits, CBlockHeader& header_orig, uint32_t offset, uint32_t step, std::atomic<bool>& found)
static void grind_task(uint32_t nBits, CBlockHeader header, uint32_t offset, uint32_t step, std::atomic<bool>& found, uint32_t& proposed_nonce)
{
arith_uint256 target;
bool neg, over;
target.SetCompact(nBits, &neg, &over);
if (target == 0 || neg || over) return;
CBlockHeader header = header_orig; // working copy
header.nNonce = offset;
uint32_t finish = std::numeric_limits<uint32_t>::max() - step;
@ -99,7 +98,7 @@ static void grind_task(uint32_t nBits, CBlockHeader& header_orig, uint32_t offse
do {
if (UintToArith256(header.GetHash()) <= target) {
if (!found.exchange(true)) {
header_orig.nNonce = header.nNonce;
proposed_nonce = header.nNonce;
}
return;
}
@ -123,16 +122,19 @@ static int Grind(const std::vector<std::string>& args, std::string& strPrint)
uint32_t nBits = header.nBits;
std::atomic<bool> found{false};
uint32_t proposed_nonce{};
std::vector<std::thread> threads;
int n_tasks = std::max(1u, std::thread::hardware_concurrency());
for (int i = 0; i < n_tasks; ++i) {
threads.emplace_back( grind_task, nBits, std::ref(header), i, n_tasks, std::ref(found) );
threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found), std::ref(proposed_nonce));
}
for (auto& t : threads) {
t.join();
}
if (!found) {
if (found) {
header.nNonce = proposed_nonce;
} else {
strPrint = "Could not satisfy difficulty target";
return EXIT_FAILURE;
}