From a683cc85d925f4133f850023540587a2e6e1d9ff Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 5 May 2016 17:05:27 +1200 Subject: [PATCH] Merge *StepRow XOR and trimming operations --- src/crypto/equihash.cpp | 124 ++++++++++++++++++---------------------- src/crypto/equihash.h | 18 +----- 2 files changed, 60 insertions(+), 82 deletions(-) diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 77a4d585..e66e8e05 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -77,6 +77,31 @@ FullStepRow::FullStepRow(unsigned int n, const eh_HashState& base_state, eh_inde assert(indices.size() == 1); } +FullStepRow::FullStepRow(const FullStepRow& a, const FullStepRow& b, int trim) : + StepRow {a} +{ + if (a.len != b.len) { + throw std::invalid_argument("Hash length differs"); + } + if (a.indices.size() != b.indices.size()) { + throw std::invalid_argument("Number of indices differs"); + } + unsigned char* p = new unsigned char[a.len-trim]; + for (int i = trim; i < a.len; i++) + p[i-trim] = a.hash[i] ^ b.hash[i]; + delete[] hash; + hash = p; + len = a.len-trim; + indices.reserve(a.indices.size() + b.indices.size()); + if (a.IndicesBefore(b)) { + indices.insert(indices.end(), a.indices.begin(), a.indices.end()); + indices.insert(indices.end(), b.indices.begin(), b.indices.end()); + } else { + indices.insert(indices.end(), b.indices.begin(), b.indices.end()); + indices.insert(indices.end(), a.indices.begin(), a.indices.end()); + } +} + FullStepRow& FullStepRow::operator=(const FullStepRow& a) { unsigned char* p = new unsigned char[a.len]; @@ -88,33 +113,6 @@ FullStepRow& FullStepRow::operator=(const FullStepRow& a) return *this; } -FullStepRow& FullStepRow::operator^=(const FullStepRow& a) -{ - if (a.len != len) { - throw std::invalid_argument("Hash length differs"); - } - if (a.indices.size() != indices.size()) { - throw std::invalid_argument("Number of indices differs"); - } - unsigned char* p = new unsigned char[len]; - for (int i = 0; i < len; i++) - p[i] = hash[i] ^ a.hash[i]; - delete[] hash; - hash = p; - indices.reserve(indices.size() + a.indices.size()); - indices.insert(indices.end(), a.indices.begin(), a.indices.end()); - return *this; -} - -void FullStepRow::TrimHash(int l) -{ - unsigned char* p = new unsigned char[len-l]; - std::copy(hash+l, hash+len, p); - delete[] hash; - hash = p; - len -= l; -} - bool StepRow::IsZero() { char res = 0; @@ -178,6 +176,31 @@ TruncatedStepRow::TruncatedStepRow(const TruncatedStepRow& a) : hash = p; } +TruncatedStepRow::TruncatedStepRow(const TruncatedStepRow& a, const TruncatedStepRow& b, int trim) : + StepRow {a}, + lenIndices {a.lenIndices+b.lenIndices} +{ + if (a.len != b.len) { + throw std::invalid_argument("Hash length differs"); + } + if (a.lenIndices != b.lenIndices) { + throw std::invalid_argument("Number of indices differs"); + } + unsigned char* p = new unsigned char[a.len-trim+a.lenIndices+b.lenIndices]; + for (int i = trim; i < a.len; i++) + p[i-trim] = a.hash[i] ^ b.hash[i]; + len = a.len-trim; + if (a.IndicesBefore(b)) { + std::copy(a.hash+a.len, a.hash+a.len+a.lenIndices, p+len); + std::copy(b.hash+b.len, b.hash+b.len+b.lenIndices, p+len+a.lenIndices); + } else { + std::copy(b.hash+b.len, b.hash+b.len+b.lenIndices, p+len); + std::copy(a.hash+a.len, a.hash+a.len+a.lenIndices, p+len+b.lenIndices); + } + delete[] hash; + hash = p; +} + TruncatedStepRow& TruncatedStepRow::operator=(const TruncatedStepRow& a) { unsigned char* p = new unsigned char[a.len+a.lenIndices]; @@ -189,34 +212,6 @@ TruncatedStepRow& TruncatedStepRow::operator=(const TruncatedStepRow& a) return *this; } -TruncatedStepRow& TruncatedStepRow::operator^=(const TruncatedStepRow& a) -{ - if (a.len != len) { - throw std::invalid_argument("Hash length differs"); - } - if (a.lenIndices != lenIndices) { - throw std::invalid_argument("Number of indices differs"); - } - unsigned char* p = new unsigned char[len+lenIndices+a.lenIndices]; - for (int i = 0; i < len; i++) - p[i] = hash[i] ^ a.hash[i]; - std::copy(hash+len, hash+len+lenIndices, p+len); - std::copy(a.hash+a.len, a.hash+a.len+a.lenIndices, p+len+lenIndices); - delete[] hash; - hash = p; - lenIndices += a.lenIndices; - return *this; -} - -void TruncatedStepRow::TrimHash(int l) -{ - unsigned char* p = new unsigned char[len-l+lenIndices]; - std::copy(hash+l, hash+len+lenIndices, p); - delete[] hash; - hash = p; - len -= l; -} - eh_trunc* TruncatedStepRow::GetPartialSolution(eh_index soln_size) const { assert(lenIndices == soln_size); @@ -261,8 +256,7 @@ std::set> Equihash::BasicSolve(const eh_HashState& ba for (int l = 0; l < j - 1; l++) { for (int m = l + 1; m < j; m++) { if (DistinctIndices(X[i+l], X[i+m])) { - Xc.push_back(X[i+l] ^ X[i+m]); - Xc.back().TrimHash(CollisionByteLength); + Xc.emplace_back(X[i+l], X[i+m], CollisionByteLength); } } } @@ -300,7 +294,7 @@ std::set> Equihash::BasicSolve(const eh_HashState& ba std::sort(X.begin(), X.end()); LogPrint("pow", "- Finding collisions\n"); for (int i = 0; i < X.size() - 1; i++) { - FullStepRow res = X[i] ^ X[i+1]; + FullStepRow res(X[i], X[i+1], 0); if (res.IsZero() && DistinctIndices(X[i], X[i+1])) { solns.insert(res.GetSolution()); } @@ -329,11 +323,9 @@ void CollideBranches(std::vector& X, const unsigned int clen, const for (int m = l + 1; m < j; m++) { if (DistinctIndices(X[i+l], X[i+m])) { if (IsValidBranch(X[i+l], ilen, lt) && IsValidBranch(X[i+m], ilen, rt)) { - Xc.push_back(X[i+l] ^ X[i+m]); - Xc.back().TrimHash(clen); + Xc.emplace_back(X[i+l], X[i+m], clen); } else if (IsValidBranch(X[i+m], ilen, lt) && IsValidBranch(X[i+l], ilen, rt)) { - Xc.push_back(X[i+m] ^ X[i+l]); - Xc.back().TrimHash(clen); + Xc.emplace_back(X[i+m], X[i+l], clen); } } } @@ -406,8 +398,7 @@ std::set> Equihash::OptimisedSolve(const eh_HashState 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.push_back(Xt[i+l] ^ Xt[i+m]); - Xc.back().TrimHash(CollisionByteLength); + Xc.emplace_back(Xt[i+l], Xt[i+m], CollisionByteLength); } } @@ -443,7 +434,7 @@ std::set> Equihash::OptimisedSolve(const eh_HashState std::sort(Xt.begin(), Xt.end()); LogPrint("pow", "- Finding collisions\n"); for (int i = 0; i < Xt.size() - 1; i++) { - TruncatedStepRow res = Xt[i] ^ Xt[i+1]; + TruncatedStepRow res(Xt[i], Xt[i+1], 0); if (res.IsZero()) { partialSolns.push_back(res.GetPartialSolution(soln_size)); } @@ -548,8 +539,7 @@ bool Equihash::IsValidSolution(const eh_HashState& base_state, std::vector< LogPrint("pow", "Invalid solution: duplicate indices\n"); return false; } - Xc.push_back(X[i] ^ X[i+1]); - Xc.back().TrimHash(CollisionByteLength); + Xc.emplace_back(X[i], X[i+1], CollisionByteLength); } X = Xc; } diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 4e067155..22b8cc89 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -54,18 +54,12 @@ public: ~FullStepRow() { } FullStepRow(const FullStepRow& a) : StepRow {a}, indices(a.indices) { } + FullStepRow(const FullStepRow& a, const FullStepRow& b, int trim); FullStepRow& operator=(const FullStepRow& a); - FullStepRow& operator^=(const FullStepRow& a); - void TrimHash(int l); - bool IndicesBefore(const FullStepRow& a) { return indices[0] < a.indices[0]; } + inline bool IndicesBefore(const FullStepRow& a) const { return indices[0] < a.indices[0]; } std::vector GetSolution() { return std::vector(indices); } - friend inline const FullStepRow operator^(const FullStepRow& a, const FullStepRow& b) { - if (a.indices[0] < b.indices[0]) { return FullStepRow(a) ^= b; } - else { return FullStepRow(b) ^= a; } - } - friend bool DistinctIndices(const FullStepRow& a, const FullStepRow& b); friend bool IsValidBranch(const FullStepRow& a, const unsigned int ilen, const eh_trunc t); }; @@ -83,17 +77,11 @@ public: ~TruncatedStepRow() { } TruncatedStepRow(const TruncatedStepRow& a); + TruncatedStepRow(const TruncatedStepRow& a, const TruncatedStepRow& b, int trim); TruncatedStepRow& operator=(const TruncatedStepRow& a); - TruncatedStepRow& operator^=(const TruncatedStepRow& a); - void TrimHash(int l); inline bool IndicesBefore(const TruncatedStepRow& a) const { return memcmp(hash+len, a.hash+a.len, lenIndices) < 0; } eh_trunc* GetPartialSolution(eh_index soln_size) const; - - friend inline const TruncatedStepRow operator^(const TruncatedStepRow& a, const TruncatedStepRow& b) { - if (a.IndicesBefore(b)) { return TruncatedStepRow(a) ^= b; } - else { return TruncatedStepRow(b) ^= a; } - } }; template