Skip to content

Commit

Permalink
Equihash: Pass each obtained solution to a callback for immediate che…
Browse files Browse the repository at this point in the history
…cking

Closes zcash#1143
  • Loading branch information
str4d committed Jul 27, 2016
1 parent 6dfc9e7 commit 51eb527
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 98 deletions.
46 changes: 31 additions & 15 deletions src/crypto/equihash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,9 @@ std::shared_ptr<eh_trunc> TruncatedStepRow<WIDTH>::GetTruncatedIndices(size_t le
}

template<unsigned int N, unsigned int K>
std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled)
bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled)
{
eh_index init_size { 1 << (CollisionBitLength + 1) };

Expand Down Expand Up @@ -269,7 +271,6 @@ std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& ba

// k+1) Find a collision on last 2n(k+1) bits
LogPrint("pow", "Final round:\n");
std::set<std::vector<eh_index>> solns;
if (X.size() > 1) {
LogPrint("pow", "- Sorting list\n");
std::sort(X.begin(), X.end(), CompareSR(hashLen));
Expand All @@ -286,8 +287,9 @@ std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& ba
for (int l = 0; l < j - 1; l++) {
for (int m = l + 1; m < j; m++) {
FullStepRow<FinalFullWidth> res(X[i+l], X[i+m], hashLen, lenIndices, 0);
if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices)) {
solns.insert(res.GetIndices(hashLen, 2*lenIndices));
if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices) &&
validBlock(res.GetIndices(hashLen, 2*lenIndices))) {
return true;
}
}
}
Expand All @@ -298,7 +300,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& ba
} else
LogPrint("pow", "- List is empty\n");

return solns;
return false;
}

template<size_t WIDTH>
Expand Down Expand Up @@ -354,7 +356,9 @@ void CollideBranches(std::vector<FullStepRow<WIDTH>>& X, const size_t hlen, cons
}

template<unsigned int N, unsigned int K>
std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled)
bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled)
{
eh_index init_size { 1 << (CollisionBitLength + 1) };
eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength + 1) };
Expand All @@ -363,7 +367,6 @@ std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState

eh_index soln_size { 1 << K };
std::vector<std::shared_ptr<eh_trunc>> partialSolns;
std::set<std::vector<eh_index>> solns;
int invalidCount = 0;
{

Expand Down Expand Up @@ -531,7 +534,8 @@ std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState
// We are at the top of the tree
assert(X.size() == K+1);
for (FullStepRow<FinalFullWidth> row : *X[K]) {
solns.insert(row.GetIndices(hashLen, lenIndices));
if (validBlock(row.GetIndices(hashLen, lenIndices)))
return true;
}
if (cancelled(PartialEnd)) throw solver_cancelled;
continue;
Expand All @@ -541,7 +545,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState
}
LogPrint("pow", "- Number of invalid solutions found: %d\n", invalidCount);

return solns;
return false;
}

template<unsigned int N, unsigned int K>
Expand Down Expand Up @@ -591,18 +595,30 @@ bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<

// Explicit instantiations for Equihash<96,3>
template int Equihash<96,3>::InitialiseState(eh_HashState& base_state);
template std::set<std::vector<eh_index>> Equihash<96,3>::BasicSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
template std::set<std::vector<eh_index>> Equihash<96,3>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<96,3>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<96,3>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<96,3>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);

// Explicit instantiations for Equihash<96,5>
template int Equihash<96,5>::InitialiseState(eh_HashState& base_state);
template std::set<std::vector<eh_index>> Equihash<96,5>::BasicSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
template std::set<std::vector<eh_index>> Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<96,5>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<96,5>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);

// Explicit instantiations for Equihash<48,5>
template int Equihash<48,5>::InitialiseState(eh_HashState& base_state);
template std::set<std::vector<eh_index>> Equihash<48,5>::BasicSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
template std::set<std::vector<eh_index>> Equihash<48,5>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<48,5>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<48,5>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
template bool Equihash<48,5>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
72 changes: 47 additions & 25 deletions src/crypto/equihash.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,12 @@ class Equihash
Equihash() { }

int InitialiseState(eh_HashState& base_state);
std::set<std::vector<eh_index>> BasicSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
std::set<std::vector<eh_index>> OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
bool BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
bool OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
bool IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
};

Expand All @@ -177,31 +181,49 @@ static Equihash<48,5> Eh48_5;
throw std::invalid_argument("Unsupported Equihash parameters"); \
}

#define EhBasicSolve(n, k, base_state, solns, cancelled) \
if (n == 96 && k == 3) { \
solns = Eh96_3.BasicSolve(base_state, cancelled); \
} else if (n == 96 && k == 5) { \
solns = Eh96_5.BasicSolve(base_state, cancelled); \
} else if (n == 48 && k == 5) { \
solns = Eh48_5.BasicSolve(base_state, cancelled); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
inline bool EhBasicSolve(unsigned int n, unsigned int k, const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled)
{
if (n == 96 && k == 3) {
return Eh96_3.BasicSolve(base_state, validBlock, cancelled);
} else if (n == 96 && k == 5) {
return Eh96_5.BasicSolve(base_state, validBlock, cancelled);
} else if (n == 48 && k == 5) {
return Eh48_5.BasicSolve(base_state, validBlock, cancelled);
} else {
throw std::invalid_argument("Unsupported Equihash parameters");
}
#define EhBasicSolveUncancellable(n, k, base_state, solns) \
EhBasicSolve(n, k, base_state, solns, [](EhSolverCancelCheck pos) { return false; })

#define EhOptimisedSolve(n, k, base_state, solns, cancelled) \
if (n == 96 && k == 3) { \
solns = Eh96_3.OptimisedSolve(base_state, cancelled); \
} else if (n == 96 && k == 5) { \
solns = Eh96_5.OptimisedSolve(base_state, cancelled); \
} else if (n == 48 && k == 5) { \
solns = Eh48_5.OptimisedSolve(base_state, cancelled); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
}

inline bool EhBasicSolveUncancellable(unsigned int n, unsigned int k, const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock)
{
return EhBasicSolve(n, k, base_state, validBlock,
[](EhSolverCancelCheck pos) { return false; });
}

inline bool EhOptimisedSolve(unsigned int n, unsigned int k, const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled)
{
if (n == 96 && k == 3) {
return Eh96_3.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == 96 && k == 5) {
return Eh96_5.OptimisedSolve(base_state, validBlock, cancelled);
} else if (n == 48 && k == 5) {
return Eh48_5.OptimisedSolve(base_state, validBlock, cancelled);
} else {
throw std::invalid_argument("Unsupported Equihash parameters");
}
#define EhOptimisedSolveUncancellable(n, k, base_state, solns) \
EhOptimisedSolve(n, k, base_state, solns, [](EhSolverCancelCheck pos) { return false; })
}

inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const eh_HashState& base_state,
const std::function<bool(std::vector<eh_index>)> validBlock)
{
return EhOptimisedSolve(n, k, base_state, validBlock,
[](EhSolverCancelCheck pos) { return false; });
}

#define EhIsValidSolution(n, k, base_state, soln, ret) \
if (n == 96 && k == 3) { \
Expand Down
Loading

0 comments on commit 51eb527

Please sign in to comment.