Merge *StepRow XOR and trimming operations
This commit is contained in:
parent
e95747288a
commit
a683cc85d9
|
@ -77,6 +77,31 @@ FullStepRow::FullStepRow(unsigned int n, const eh_HashState& base_state, eh_inde
|
||||||
assert(indices.size() == 1);
|
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)
|
FullStepRow& FullStepRow::operator=(const FullStepRow& a)
|
||||||
{
|
{
|
||||||
unsigned char* p = new unsigned char[a.len];
|
unsigned char* p = new unsigned char[a.len];
|
||||||
|
@ -88,33 +113,6 @@ FullStepRow& FullStepRow::operator=(const FullStepRow& a)
|
||||||
return *this;
|
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()
|
bool StepRow::IsZero()
|
||||||
{
|
{
|
||||||
char res = 0;
|
char res = 0;
|
||||||
|
@ -178,6 +176,31 @@ TruncatedStepRow::TruncatedStepRow(const TruncatedStepRow& a) :
|
||||||
hash = p;
|
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)
|
TruncatedStepRow& TruncatedStepRow::operator=(const TruncatedStepRow& a)
|
||||||
{
|
{
|
||||||
unsigned char* p = new unsigned char[a.len+a.lenIndices];
|
unsigned char* p = new unsigned char[a.len+a.lenIndices];
|
||||||
|
@ -189,34 +212,6 @@ TruncatedStepRow& TruncatedStepRow::operator=(const TruncatedStepRow& a)
|
||||||
return *this;
|
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
|
eh_trunc* TruncatedStepRow::GetPartialSolution(eh_index soln_size) const
|
||||||
{
|
{
|
||||||
assert(lenIndices == soln_size);
|
assert(lenIndices == soln_size);
|
||||||
|
@ -261,8 +256,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& ba
|
||||||
for (int l = 0; l < j - 1; l++) {
|
for (int l = 0; l < j - 1; l++) {
|
||||||
for (int m = l + 1; m < j; m++) {
|
for (int m = l + 1; m < j; m++) {
|
||||||
if (DistinctIndices(X[i+l], X[i+m])) {
|
if (DistinctIndices(X[i+l], X[i+m])) {
|
||||||
Xc.push_back(X[i+l] ^ X[i+m]);
|
Xc.emplace_back(X[i+l], X[i+m], CollisionByteLength);
|
||||||
Xc.back().TrimHash(CollisionByteLength);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,7 +294,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& ba
|
||||||
std::sort(X.begin(), X.end());
|
std::sort(X.begin(), X.end());
|
||||||
LogPrint("pow", "- Finding collisions\n");
|
LogPrint("pow", "- Finding collisions\n");
|
||||||
for (int i = 0; i < X.size() - 1; i++) {
|
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])) {
|
if (res.IsZero() && DistinctIndices(X[i], X[i+1])) {
|
||||||
solns.insert(res.GetSolution());
|
solns.insert(res.GetSolution());
|
||||||
}
|
}
|
||||||
|
@ -329,11 +323,9 @@ void CollideBranches(std::vector<FullStepRow>& X, const unsigned int clen, const
|
||||||
for (int m = l + 1; m < j; m++) {
|
for (int m = l + 1; m < j; m++) {
|
||||||
if (DistinctIndices(X[i+l], X[i+m])) {
|
if (DistinctIndices(X[i+l], X[i+m])) {
|
||||||
if (IsValidBranch(X[i+l], ilen, lt) && IsValidBranch(X[i+m], ilen, rt)) {
|
if (IsValidBranch(X[i+l], ilen, lt) && IsValidBranch(X[i+m], ilen, rt)) {
|
||||||
Xc.push_back(X[i+l] ^ X[i+m]);
|
Xc.emplace_back(X[i+l], X[i+m], clen);
|
||||||
Xc.back().TrimHash(clen);
|
|
||||||
} else if (IsValidBranch(X[i+m], ilen, lt) && IsValidBranch(X[i+l], ilen, rt)) {
|
} else if (IsValidBranch(X[i+m], ilen, lt) && IsValidBranch(X[i+l], ilen, rt)) {
|
||||||
Xc.push_back(X[i+m] ^ X[i+l]);
|
Xc.emplace_back(X[i+m], X[i+l], clen);
|
||||||
Xc.back().TrimHash(clen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,8 +398,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState
|
||||||
for (int l = 0; l < j - 1; l++) {
|
for (int l = 0; l < j - 1; l++) {
|
||||||
for (int m = l + 1; m < j; m++) {
|
for (int m = l + 1; m < j; m++) {
|
||||||
// We truncated, so don't check for distinct indices here
|
// We truncated, so don't check for distinct indices here
|
||||||
Xc.push_back(Xt[i+l] ^ Xt[i+m]);
|
Xc.emplace_back(Xt[i+l], Xt[i+m], CollisionByteLength);
|
||||||
Xc.back().TrimHash(CollisionByteLength);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +434,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState
|
||||||
std::sort(Xt.begin(), Xt.end());
|
std::sort(Xt.begin(), Xt.end());
|
||||||
LogPrint("pow", "- Finding collisions\n");
|
LogPrint("pow", "- Finding collisions\n");
|
||||||
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], 0);
|
||||||
if (res.IsZero()) {
|
if (res.IsZero()) {
|
||||||
partialSolns.push_back(res.GetPartialSolution(soln_size));
|
partialSolns.push_back(res.GetPartialSolution(soln_size));
|
||||||
}
|
}
|
||||||
|
@ -548,8 +539,7 @@ bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<
|
||||||
LogPrint("pow", "Invalid solution: duplicate indices\n");
|
LogPrint("pow", "Invalid solution: duplicate indices\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Xc.push_back(X[i] ^ X[i+1]);
|
Xc.emplace_back(X[i], X[i+1], CollisionByteLength);
|
||||||
Xc.back().TrimHash(CollisionByteLength);
|
|
||||||
}
|
}
|
||||||
X = Xc;
|
X = Xc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,18 +54,12 @@ public:
|
||||||
~FullStepRow() { }
|
~FullStepRow() { }
|
||||||
|
|
||||||
FullStepRow(const FullStepRow& a) : StepRow {a}, indices(a.indices) { }
|
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);
|
||||||
FullStepRow& operator^=(const FullStepRow& a);
|
|
||||||
|
|
||||||
void TrimHash(int l);
|
inline bool IndicesBefore(const FullStepRow& a) const { return indices[0] < a.indices[0]; }
|
||||||
bool IndicesBefore(const FullStepRow& a) { return indices[0] < a.indices[0]; }
|
|
||||||
std::vector<eh_index> GetSolution() { return std::vector<eh_index>(indices); }
|
std::vector<eh_index> GetSolution() { return std::vector<eh_index>(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 DistinctIndices(const FullStepRow& a, const FullStepRow& b);
|
||||||
friend bool IsValidBranch(const FullStepRow& a, const unsigned int ilen, const eh_trunc t);
|
friend bool IsValidBranch(const FullStepRow& a, const unsigned int ilen, const eh_trunc t);
|
||||||
};
|
};
|
||||||
|
@ -83,17 +77,11 @@ public:
|
||||||
~TruncatedStepRow() { }
|
~TruncatedStepRow() { }
|
||||||
|
|
||||||
TruncatedStepRow(const TruncatedStepRow& a);
|
TruncatedStepRow(const TruncatedStepRow& a);
|
||||||
|
TruncatedStepRow(const TruncatedStepRow& a, const TruncatedStepRow& b, int trim);
|
||||||
TruncatedStepRow& operator=(const TruncatedStepRow& a);
|
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; }
|
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;
|
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<unsigned int N, unsigned int K>
|
template<unsigned int N, unsigned int K>
|
||||||
|
|
Loading…
Reference in New Issue