From d4af3dd5fd827d6531f2ef102bf34fd6ad7b6b67 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Aug 2016 13:07:24 +1200 Subject: [PATCH 1/5] Eliminate some of the duplicates caused by truncating indices --- src/crypto/equihash.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index cc9804752..31cb4319f 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -303,6 +303,28 @@ bool Equihash::BasicSolve(const eh_HashState& base_state, return false; } +bool IsProbablyDuplicate(std::shared_ptr indices, size_t lenIndices) +{ + bool checked_index[lenIndices] = {false}; + for (int z = 0; z < lenIndices; z++) { + 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; + checked_index[z] = true; + break; + } + } + } + } + bool is_probably_duplicate = true; + for (int z = 0; z < lenIndices && is_probably_duplicate; z++) { + is_probably_duplicate &= checked_index[z]; + } + return is_probably_duplicate; +} + 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) { @@ -402,10 +424,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); + } } } From 6b4f4475a5110d44d50f9b79a88cd9c6ffdad913 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Aug 2016 17:18:47 +1200 Subject: [PATCH 2/5] Use fixed-size array in IsProbablyDuplicate to avoid stack protector warning --- src/crypto/equihash.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 31cb4319f..d2686a263 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -303,9 +303,10 @@ bool Equihash::BasicSolve(const eh_HashState& base_state, return false; } +template bool IsProbablyDuplicate(std::shared_ptr indices, size_t lenIndices) { - bool checked_index[lenIndices] = {false}; + bool checked_index[MAX_INDICES] = {false}; for (int z = 0; z < lenIndices; z++) { if (!checked_index[z]) { for (int y = z+1; y < lenIndices; y++) { @@ -387,7 +388,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; { @@ -432,8 +433,8 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, hashLen, lenIndices, CollisionByteLength}; if (!(Xi.IsZero(hashLen-CollisionByteLength) && - IsProbablyDuplicate(Xi.GetTruncatedIndices(hashLen-CollisionByteLength, 2*lenIndices), - 2*lenIndices))) { + IsProbablyDuplicate(Xi.GetTruncatedIndices(hashLen-CollisionByteLength, 2*lenIndices), + 2*lenIndices))) { Xc.emplace_back(Xi); } } From 3c654f38eb623e413238a596ee3397d0139a1dd1 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Aug 2016 18:15:34 +1200 Subject: [PATCH 3/5] Eliminate probably duplicates in final round This is more likely to eliminate valid solutions than doing so in intermediate rounds, but the probability is still very low. --- src/crypto/equihash.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index d2686a263..9c018d72f 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -487,8 +487,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); + } } } From e999c1e339b540bff025ce42904a7a5b7251117e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Aug 2016 22:12:50 +1200 Subject: [PATCH 4/5] Simplify IsProbablyDuplicate() --- src/crypto/equihash.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 9c018d72f..3706b0c9e 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -307,23 +307,21 @@ template bool IsProbablyDuplicate(std::shared_ptr indices, size_t lenIndices) { 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; - checked_index[z] = true; + count_checked += 2; break; } } } } - bool is_probably_duplicate = true; - for (int z = 0; z < lenIndices && is_probably_duplicate; z++) { - is_probably_duplicate &= checked_index[z]; - } - return is_probably_duplicate; + return count_checked == lenIndices; } template From 3c3ef34505a5e907243e134ac9a90376b673a0c0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Aug 2016 22:24:04 +1200 Subject: [PATCH 5/5] Add missing assert --- src/crypto/equihash.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 3706b0c9e..2bd7b7ada 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -306,6 +306,7 @@ bool Equihash::BasicSolve(const eh_HashState& base_state, 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++) {