diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 5f6f4eaec..57a5f4dac 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -317,6 +317,28 @@ bool Equihash::BasicSolve(const eh_HashState& base_state, return false; } +template +bool IsProbablyDuplicate(std::shared_ptr indices, size_t lenIndices) +{ + assert(lenIndices <= MAX_INDICES); + bool checked_index[MAX_INDICES] = {false}; + bool count_checked = 0; + for (int z = 0; z < lenIndices; z++) { + // Skip over indices we have already paired + if (!checked_index[z]) { + for (int y = z+1; y < lenIndices; y++) { + if (!checked_index[y] && indices.get()[z] == indices.get()[y]) { + // Pair found + checked_index[y] = true; + count_checked += 2; + break; + } + } + } + } + return count_checked == lenIndices; +} + template void CollideBranches(std::vector>& X, const size_t hlen, const size_t lenIndices, const unsigned int clen, const unsigned int ilen, const eh_trunc lt, const eh_trunc rt) { @@ -379,7 +401,7 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, // First run the algorithm with truncated indices - eh_index soln_size { 1 << K }; + const eh_index soln_size { 1 << K }; std::vector> partialSolns; int invalidCount = 0; { @@ -417,10 +439,18 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, } // 2c) Calculate tuples (X_i ^ X_j, (i, j)) + bool checking_for_zero = (i == 0 && Xt[0].IsZero(hashLen)); for (int l = 0; l < j - 1; l++) { for (int m = l + 1; m < j; m++) { // We truncated, so don't check for distinct indices here - Xc.emplace_back(Xt[i+l], Xt[i+m], hashLen, lenIndices, CollisionByteLength); + TruncatedStepRow Xi {Xt[i+l], Xt[i+m], + hashLen, lenIndices, + CollisionByteLength}; + if (!(Xi.IsZero(hashLen-CollisionByteLength) && + IsProbablyDuplicate(Xi.GetTruncatedIndices(hashLen-CollisionByteLength, 2*lenIndices), + 2*lenIndices))) { + Xc.emplace_back(Xi); + } } } @@ -471,8 +501,12 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, for (int l = 0; l < j - 1; l++) { for (int m = l + 1; m < j; m++) { - TruncatedStepRow res(Xt[i+l], Xt[i+m], hashLen, lenIndices, 0); - partialSolns.push_back(res.GetTruncatedIndices(hashLen, 2*lenIndices)); + TruncatedStepRow res(Xt[i+l], Xt[i+m], + hashLen, lenIndices, 0); + auto soln = res.GetTruncatedIndices(hashLen, 2*lenIndices); + if (!IsProbablyDuplicate(soln, 2*lenIndices)) { + partialSolns.push_back(soln); + } } }