Browse Source

Store truncated indices in the same char* as the hash (H/T tromp for the idea!)

pull/145/head
Jack Grigg 8 years ago
parent
commit
39f5cb35f9
  1. 66
      src/crypto/equihash.cpp
  2. 11
      src/crypto/equihash.h

66
src/crypto/equihash.cpp

@ -172,19 +172,33 @@ bool IsValidBranch(const FullStepRow& a, const unsigned int ilen, const eh_trunc
TruncatedStepRow::TruncatedStepRow(unsigned int n, const eh_HashState& base_state, eh_index i, unsigned int ilen) : TruncatedStepRow::TruncatedStepRow(unsigned int n, const eh_HashState& base_state, eh_index i, unsigned int ilen) :
StepRow {n, base_state, i}, StepRow {n, base_state, i},
indices {TruncateIndex(i, ilen)} lenIndices {1}
{ {
assert(indices.size() == 1); unsigned char* p = new unsigned char[len+lenIndices];
std::copy(hash, hash+len, p);
p[len] = TruncateIndex(i, ilen);
delete[] hash;
hash = p;
}
TruncatedStepRow::TruncatedStepRow(const TruncatedStepRow& a) :
StepRow {a},
lenIndices {a.lenIndices}
{
unsigned char* p = new unsigned char[a.len+a.lenIndices];
std::copy(a.hash, a.hash+a.len+a.lenIndices, p);
delete[] hash;
hash = p;
} }
TruncatedStepRow& TruncatedStepRow::operator=(const TruncatedStepRow& a) TruncatedStepRow& TruncatedStepRow::operator=(const TruncatedStepRow& a)
{ {
unsigned char* p = new unsigned char[a.len]; unsigned char* p = new unsigned char[a.len+a.lenIndices];
std::copy(a.hash, a.hash+a.len, p); std::copy(a.hash, a.hash+a.len+a.lenIndices, p);
delete[] hash; delete[] hash;
hash = p; hash = p;
len = a.len; len = a.len;
indices = a.indices; lenIndices = a.lenIndices;
return *this; return *this;
} }
@ -193,19 +207,37 @@ TruncatedStepRow& TruncatedStepRow::operator^=(const TruncatedStepRow& a)
if (a.len != len) { if (a.len != len) {
throw std::invalid_argument("Hash length differs"); throw std::invalid_argument("Hash length differs");
} }
if (a.indices.size() != indices.size()) { if (a.lenIndices != lenIndices) {
throw std::invalid_argument("Number of indices differs"); throw std::invalid_argument("Number of indices differs");
} }
unsigned char* p = new unsigned char[len]; unsigned char* p = new unsigned char[len+lenIndices+a.lenIndices];
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
p[i] = hash[i] ^ a.hash[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; delete[] hash;
hash = p; hash = p;
indices.reserve(indices.size() + a.indices.size()); lenIndices += a.lenIndices;
indices.insert(indices.end(), a.indices.begin(), a.indices.end());
return *this; 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);
eh_trunc* p = new eh_trunc[lenIndices];
std::copy(hash+len, hash+len+lenIndices, p);
return p;
}
Equihash::Equihash(unsigned int n, unsigned int k) : Equihash::Equihash(unsigned int n, unsigned int k) :
n(n), k(k) n(n), k(k)
{ {
@ -358,7 +390,8 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
// First run the algorithm with truncated indices // First run the algorithm with truncated indices
std::vector<std::vector<eh_trunc>> partialSolns; eh_index soln_size { 1 << k };
std::vector<eh_trunc*> partialSolns;
{ {
// 1) Generate first list // 1) Generate first list
@ -431,7 +464,7 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
for (int i = 0; i < Xt.size() - 1; i++) { for (int i = 0; i < Xt.size() - 1; i++) {
TruncatedStepRow res = Xt[i] ^ Xt[i+1]; TruncatedStepRow res = Xt[i] ^ Xt[i+1];
if (res.IsZero()) { if (res.IsZero()) {
partialSolns.push_back(res.GetPartialSolution()); partialSolns.push_back(res.GetPartialSolution(soln_size));
} }
} }
} else } else
@ -446,11 +479,11 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
std::set<std::vector<eh_index>> solns; std::set<std::vector<eh_index>> solns;
eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength() + 1) }; eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength() + 1) };
int invalidCount = 0; int invalidCount = 0;
for (std::vector<eh_trunc> partialSoln : partialSolns) { for (eh_trunc* partialSoln : partialSolns) {
// 1) Generate first list of possibilities // 1) Generate first list of possibilities
std::vector<std::vector<FullStepRow>> X; std::vector<std::vector<FullStepRow>> X;
X.reserve(partialSoln.size()); X.reserve(soln_size);
for (int i = 0; i < partialSoln.size(); i++) { for (eh_index i = 0; i < soln_size; i++) {
std::vector<FullStepRow> ic; std::vector<FullStepRow> ic;
ic.reserve(recreate_size); ic.reserve(recreate_size);
for (eh_index j = 0; j < recreate_size; j++) { for (eh_index j = 0; j < recreate_size; j++) {
@ -489,10 +522,13 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
for (FullStepRow row : X[0]) { for (FullStepRow row : X[0]) {
solns.insert(row.GetSolution()); solns.insert(row.GetSolution());
} }
continue; goto deletesolution;
invalidsolution: invalidsolution:
invalidCount++; invalidCount++;
deletesolution:
delete[] partialSoln;
} }
LogPrint("pow", "- Number of invalid solutions found: %d\n", invalidCount); LogPrint("pow", "- Number of invalid solutions found: %d\n", invalidCount);

11
src/crypto/equihash.h

@ -76,21 +76,22 @@ bool IsValidBranch(const FullStepRow& a, const unsigned int ilen, const eh_trunc
class TruncatedStepRow : public StepRow class TruncatedStepRow : public StepRow
{ {
private: private:
std::vector<eh_trunc> indices; unsigned int lenIndices;
public: public:
TruncatedStepRow(unsigned int n, const eh_HashState& base_state, eh_index i, unsigned int ilen); TruncatedStepRow(unsigned int n, const eh_HashState& base_state, eh_index i, unsigned int ilen);
~TruncatedStepRow() { } ~TruncatedStepRow() { }
TruncatedStepRow(const TruncatedStepRow& a) : StepRow {a}, indices(a.indices) { } TruncatedStepRow(const TruncatedStepRow& a);
TruncatedStepRow& operator=(const TruncatedStepRow& a); TruncatedStepRow& operator=(const TruncatedStepRow& a);
TruncatedStepRow& operator^=(const TruncatedStepRow& a); TruncatedStepRow& operator^=(const TruncatedStepRow& a);
bool IndicesBefore(const TruncatedStepRow& a) { return indices[0] < a.indices[0]; } void TrimHash(int l);
std::vector<eh_trunc> GetPartialSolution() { return std::vector<eh_trunc>(indices); } 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) { friend inline const TruncatedStepRow operator^(const TruncatedStepRow& a, const TruncatedStepRow& b) {
if (a.indices[0] < b.indices[0]) { return TruncatedStepRow(a) ^= b; } if (a.IndicesBefore(b)) { return TruncatedStepRow(a) ^= b; }
else { return TruncatedStepRow(b) ^= a; } else { return TruncatedStepRow(b) ^= a; }
} }
}; };

Loading…
Cancel
Save