Auto merge of #1146 - str4d:1143-equihash-solution-callback, r=ebfull
Equihash: Pass each obtained solution to a callback for immediate checking Closes #1143
This commit is contained in:
@@ -193,7 +193,9 @@ std::shared_ptr<eh_trunc> TruncatedStepRow<WIDTH>::GetTruncatedIndices(size_t le
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int N, unsigned int K>
|
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) };
|
eh_index init_size { 1 << (CollisionBitLength + 1) };
|
||||||
|
|
||||||
@@ -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
|
// k+1) Find a collision on last 2n(k+1) bits
|
||||||
LogPrint("pow", "Final round:\n");
|
LogPrint("pow", "Final round:\n");
|
||||||
std::set<std::vector<eh_index>> solns;
|
|
||||||
if (X.size() > 1) {
|
if (X.size() > 1) {
|
||||||
LogPrint("pow", "- Sorting list\n");
|
LogPrint("pow", "- Sorting list\n");
|
||||||
std::sort(X.begin(), X.end(), CompareSR(hashLen));
|
std::sort(X.begin(), X.end(), CompareSR(hashLen));
|
||||||
@@ -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 l = 0; l < j - 1; l++) {
|
||||||
for (int m = l + 1; m < j; m++) {
|
for (int m = l + 1; m < j; m++) {
|
||||||
FullStepRow<FinalFullWidth> res(X[i+l], X[i+m], hashLen, lenIndices, 0);
|
FullStepRow<FinalFullWidth> res(X[i+l], X[i+m], hashLen, lenIndices, 0);
|
||||||
if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices)) {
|
if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices) &&
|
||||||
solns.insert(res.GetIndices(hashLen, 2*lenIndices));
|
validBlock(res.GetIndices(hashLen, 2*lenIndices))) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,7 +300,7 @@ std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& ba
|
|||||||
} else
|
} else
|
||||||
LogPrint("pow", "- List is empty\n");
|
LogPrint("pow", "- List is empty\n");
|
||||||
|
|
||||||
return solns;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t WIDTH>
|
template<size_t WIDTH>
|
||||||
@@ -354,7 +356,9 @@ void CollideBranches(std::vector<FullStepRow<WIDTH>>& X, const size_t hlen, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int N, unsigned int K>
|
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 init_size { 1 << (CollisionBitLength + 1) };
|
||||||
eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength + 1) };
|
eh_index recreate_size { UntruncateIndex(1, 0, CollisionBitLength + 1) };
|
||||||
@@ -363,7 +367,6 @@ std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState
|
|||||||
|
|
||||||
eh_index soln_size { 1 << K };
|
eh_index soln_size { 1 << K };
|
||||||
std::vector<std::shared_ptr<eh_trunc>> partialSolns;
|
std::vector<std::shared_ptr<eh_trunc>> partialSolns;
|
||||||
std::set<std::vector<eh_index>> solns;
|
|
||||||
int invalidCount = 0;
|
int invalidCount = 0;
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -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
|
// We are at the top of the tree
|
||||||
assert(X.size() == K+1);
|
assert(X.size() == K+1);
|
||||||
for (FullStepRow<FinalFullWidth> row : *X[K]) {
|
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;
|
if (cancelled(PartialEnd)) throw solver_cancelled;
|
||||||
continue;
|
continue;
|
||||||
@@ -541,7 +545,7 @@ invalidsolution:
|
|||||||
}
|
}
|
||||||
LogPrint("pow", "- Number of invalid solutions found: %d\n", invalidCount);
|
LogPrint("pow", "- Number of invalid solutions found: %d\n", invalidCount);
|
||||||
|
|
||||||
return solns;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int N, unsigned int K>
|
template<unsigned int N, unsigned int K>
|
||||||
@@ -591,18 +595,30 @@ bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<
|
|||||||
|
|
||||||
// Explicit instantiations for Equihash<96,3>
|
// Explicit instantiations for Equihash<96,3>
|
||||||
template int Equihash<96,3>::InitialiseState(eh_HashState& base_state);
|
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 bool Equihash<96,3>::BasicSolve(const eh_HashState& base_state,
|
||||||
template std::set<std::vector<eh_index>> Equihash<96,3>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
|
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);
|
template bool Equihash<96,3>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
|
||||||
|
|
||||||
// Explicit instantiations for Equihash<96,5>
|
// Explicit instantiations for Equihash<96,5>
|
||||||
template int Equihash<96,5>::InitialiseState(eh_HashState& base_state);
|
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 bool Equihash<96,5>::BasicSolve(const eh_HashState& base_state,
|
||||||
template std::set<std::vector<eh_index>> Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
|
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);
|
template bool Equihash<96,5>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
|
||||||
|
|
||||||
// Explicit instantiations for Equihash<48,5>
|
// Explicit instantiations for Equihash<48,5>
|
||||||
template int Equihash<48,5>::InitialiseState(eh_HashState& base_state);
|
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 bool Equihash<48,5>::BasicSolve(const eh_HashState& base_state,
|
||||||
template std::set<std::vector<eh_index>> Equihash<48,5>::OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
|
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);
|
template bool Equihash<48,5>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
|
||||||
|
|||||||
@@ -155,8 +155,12 @@ public:
|
|||||||
Equihash() { }
|
Equihash() { }
|
||||||
|
|
||||||
int InitialiseState(eh_HashState& base_state);
|
int InitialiseState(eh_HashState& base_state);
|
||||||
std::set<std::vector<eh_index>> BasicSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
|
bool BasicSolve(const eh_HashState& base_state,
|
||||||
std::set<std::vector<eh_index>> OptimisedSolve(const eh_HashState& base_state, const std::function<bool(EhSolverCancelCheck)> cancelled);
|
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);
|
bool IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -177,31 +181,49 @@ static Equihash<48,5> Eh48_5;
|
|||||||
throw std::invalid_argument("Unsupported Equihash parameters"); \
|
throw std::invalid_argument("Unsupported Equihash parameters"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EhBasicSolve(n, k, base_state, solns, cancelled) \
|
inline bool EhBasicSolve(unsigned int n, unsigned int k, const eh_HashState& base_state,
|
||||||
if (n == 96 && k == 3) { \
|
const std::function<bool(std::vector<eh_index>)> validBlock,
|
||||||
solns = Eh96_3.BasicSolve(base_state, cancelled); \
|
const std::function<bool(EhSolverCancelCheck)> cancelled)
|
||||||
} else if (n == 96 && k == 5) { \
|
{
|
||||||
solns = Eh96_5.BasicSolve(base_state, cancelled); \
|
if (n == 96 && k == 3) {
|
||||||
} else if (n == 48 && k == 5) { \
|
return Eh96_3.BasicSolve(base_state, validBlock, cancelled);
|
||||||
solns = Eh48_5.BasicSolve(base_state, cancelled); \
|
} else if (n == 96 && k == 5) {
|
||||||
} else { \
|
return Eh96_5.BasicSolve(base_state, validBlock, cancelled);
|
||||||
throw std::invalid_argument("Unsupported Equihash parameters"); \
|
} 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) \
|
inline bool EhBasicSolveUncancellable(unsigned int n, unsigned int k, const eh_HashState& base_state,
|
||||||
if (n == 96 && k == 3) { \
|
const std::function<bool(std::vector<eh_index>)> validBlock)
|
||||||
solns = Eh96_3.OptimisedSolve(base_state, cancelled); \
|
{
|
||||||
} else if (n == 96 && k == 5) { \
|
return EhBasicSolve(n, k, base_state, validBlock,
|
||||||
solns = Eh96_5.OptimisedSolve(base_state, cancelled); \
|
[](EhSolverCancelCheck pos) { return false; });
|
||||||
} else if (n == 48 && k == 5) { \
|
}
|
||||||
solns = Eh48_5.OptimisedSolve(base_state, cancelled); \
|
|
||||||
} else { \
|
inline bool EhOptimisedSolve(unsigned int n, unsigned int k, const eh_HashState& base_state,
|
||||||
throw std::invalid_argument("Unsupported Equihash parameters"); \
|
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) \
|
#define EhIsValidSolution(n, k, base_state, soln, ret) \
|
||||||
if (n == 96 && k == 3) { \
|
if (n == 96 && k == 3) { \
|
||||||
|
|||||||
@@ -7,76 +7,99 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
|||||||
Equihash<48,5> Eh48_5;
|
Equihash<48,5> Eh48_5;
|
||||||
crypto_generichash_blake2b_state state;
|
crypto_generichash_blake2b_state state;
|
||||||
Eh48_5.InitialiseState(state);
|
Eh48_5.InitialiseState(state);
|
||||||
std::set<std::vector<unsigned int>> solns;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == ListGeneration;
|
return pos == ListGeneration;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == ListSorting;
|
return pos == ListSorting;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == ListColliding;
|
return pos == ListColliding;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == RoundEnd;
|
return pos == RoundEnd;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == FinalSorting;
|
return pos == FinalSorting;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == FinalColliding;
|
return pos == FinalColliding;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialGeneration;
|
return pos == PartialGeneration;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialSorting;
|
return pos == PartialSorting;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialSubtreeEnd;
|
return pos == PartialSubtreeEnd;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialIndexEnd;
|
return pos == PartialIndexEnd;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialEnd;
|
return pos == PartialEnd;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -86,76 +109,99 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
|||||||
Equihash<48,5> Eh48_5;
|
Equihash<48,5> Eh48_5;
|
||||||
crypto_generichash_blake2b_state state;
|
crypto_generichash_blake2b_state state;
|
||||||
Eh48_5.InitialiseState(state);
|
Eh48_5.InitialiseState(state);
|
||||||
std::set<std::vector<unsigned int>> solns;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_NO_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == ListGeneration;
|
return pos == ListGeneration;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == ListSorting;
|
return pos == ListSorting;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == ListColliding;
|
return pos == ListColliding;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == RoundEnd;
|
return pos == RoundEnd;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == FinalSorting;
|
return pos == FinalSorting;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == FinalColliding;
|
return pos == FinalColliding;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialGeneration;
|
return pos == PartialGeneration;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialSorting;
|
return pos == PartialSorting;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialSubtreeEnd;
|
return pos == PartialSubtreeEnd;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialIndexEnd;
|
return pos == PartialIndexEnd;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](EhSolverCancelCheck pos) {
|
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||||
|
return false;
|
||||||
|
}, [](EhSolverCancelCheck pos) {
|
||||||
return pos == PartialEnd;
|
return pos == PartialEnd;
|
||||||
}), EhSolverCancelledException);
|
}), EhSolverCancelledException);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -529,26 +529,16 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||||||
// (x_1, x_2, ...) = A(I, V, n, k)
|
// (x_1, x_2, ...) = A(I, V, n, k)
|
||||||
LogPrint("pow", "Running Equihash solver with nNonce = %s\n",
|
LogPrint("pow", "Running Equihash solver with nNonce = %s\n",
|
||||||
pblock->nNonce.ToString());
|
pblock->nNonce.ToString());
|
||||||
std::set<std::vector<unsigned int>> solns;
|
|
||||||
try {
|
|
||||||
std::function<bool(EhSolverCancelCheck)> cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) {
|
|
||||||
std::lock_guard<std::mutex> lock{m_cs};
|
|
||||||
return cancelSolver;
|
|
||||||
};
|
|
||||||
EhOptimisedSolve(n, k, curr_state, solns, cancelled);
|
|
||||||
} catch (EhSolverCancelledException&) {
|
|
||||||
LogPrint("pow", "Equihash solver cancelled\n");
|
|
||||||
std::lock_guard<std::mutex> lock{m_cs};
|
|
||||||
cancelSolver = false;
|
|
||||||
}
|
|
||||||
LogPrint("pow", "Solutions: %d\n", solns.size());
|
|
||||||
|
|
||||||
// Write the solution to the hash and compute the result.
|
std::function<bool(std::vector<eh_index>)> validBlock =
|
||||||
for (auto soln : solns) {
|
[&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
|
||||||
|
(std::vector<eh_index> soln) {
|
||||||
|
// Write the solution to the hash and compute the result.
|
||||||
|
LogPrint("pow", "- Checking solution against target\n");
|
||||||
pblock->nSolution = soln;
|
pblock->nSolution = soln;
|
||||||
|
|
||||||
if (UintToArith256(pblock->GetHash()) > hashTarget) {
|
if (UintToArith256(pblock->GetHash()) > hashTarget) {
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Found a solution
|
// Found a solution
|
||||||
@@ -566,7 +556,20 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||||||
if (chainparams.MineBlocksOnDemand())
|
if (chainparams.MineBlocksOnDemand())
|
||||||
throw boost::thread_interrupted();
|
throw boost::thread_interrupted();
|
||||||
|
|
||||||
break;
|
return true;
|
||||||
|
};
|
||||||
|
std::function<bool(EhSolverCancelCheck)> cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) {
|
||||||
|
std::lock_guard<std::mutex> lock{m_cs};
|
||||||
|
return cancelSolver;
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
// If we find a valid block, we rebuild
|
||||||
|
if (EhOptimisedSolve(n, k, curr_state, validBlock, cancelled))
|
||||||
|
break;
|
||||||
|
} catch (EhSolverCancelledException&) {
|
||||||
|
LogPrint("pow", "Equihash solver cancelled\n");
|
||||||
|
std::lock_guard<std::mutex> lock{m_cs};
|
||||||
|
cancelSolver = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for stop or if block needs to be rebuilt
|
// Check for stop or if block needs to be rebuilt
|
||||||
|
|||||||
@@ -188,19 +188,13 @@ Value generate(const Array& params, bool fHelp)
|
|||||||
pblock->nNonce.size());
|
pblock->nNonce.size());
|
||||||
|
|
||||||
// (x_1, x_2, ...) = A(I, V, n, k)
|
// (x_1, x_2, ...) = A(I, V, n, k)
|
||||||
std::set<std::vector<unsigned int>> solns;
|
std::function<bool(std::vector<eh_index>)> validBlock =
|
||||||
EhBasicSolveUncancellable(n, k, curr_state, solns);
|
[&pblock](std::vector<eh_index> soln) {
|
||||||
|
|
||||||
for (auto soln : solns) {
|
|
||||||
bool isValid;
|
|
||||||
EhIsValidSolution(n, k, curr_state, soln, isValid);
|
|
||||||
assert(isValid);
|
|
||||||
pblock->nSolution = soln;
|
pblock->nSolution = soln;
|
||||||
|
return CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus());
|
||||||
if (CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
|
};
|
||||||
goto endloop;
|
if (EhBasicSolveUncancellable(n, k, curr_state, validBlock))
|
||||||
}
|
goto endloop;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
endloop:
|
endloop:
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
|
|||||||
@@ -50,7 +50,12 @@ void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, c
|
|||||||
|
|
||||||
// First test the basic solver
|
// First test the basic solver
|
||||||
std::set<std::vector<uint32_t>> ret;
|
std::set<std::vector<uint32_t>> ret;
|
||||||
EhBasicSolveUncancellable(n, k, state, ret);
|
std::function<bool(std::vector<eh_index>)> validBlock =
|
||||||
|
[&ret](std::vector<eh_index> soln) {
|
||||||
|
ret.insert(soln);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
EhBasicSolveUncancellable(n, k, state, validBlock);
|
||||||
BOOST_TEST_MESSAGE("[Basic] Number of solutions: " << ret.size());
|
BOOST_TEST_MESSAGE("[Basic] Number of solutions: " << ret.size());
|
||||||
std::stringstream strm;
|
std::stringstream strm;
|
||||||
PrintSolutions(strm, ret);
|
PrintSolutions(strm, ret);
|
||||||
@@ -59,7 +64,12 @@ void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, c
|
|||||||
|
|
||||||
// The optimised solver should have the exact same result
|
// The optimised solver should have the exact same result
|
||||||
std::set<std::vector<uint32_t>> retOpt;
|
std::set<std::vector<uint32_t>> retOpt;
|
||||||
EhOptimisedSolveUncancellable(n, k, state, retOpt);
|
std::function<bool(std::vector<eh_index>)> validBlockOpt =
|
||||||
|
[&retOpt](std::vector<eh_index> soln) {
|
||||||
|
retOpt.insert(soln);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
EhOptimisedSolveUncancellable(n, k, state, validBlockOpt);
|
||||||
BOOST_TEST_MESSAGE("[Optimised] Number of solutions: " << retOpt.size());
|
BOOST_TEST_MESSAGE("[Optimised] Number of solutions: " << retOpt.size());
|
||||||
strm.str("");
|
strm.str("");
|
||||||
PrintSolutions(strm, retOpt);
|
PrintSolutions(strm, retOpt);
|
||||||
|
|||||||
@@ -118,7 +118,8 @@ double benchmark_solve_equihash()
|
|||||||
|
|
||||||
timer_start();
|
timer_start();
|
||||||
std::set<std::vector<unsigned int>> solns;
|
std::set<std::vector<unsigned int>> solns;
|
||||||
EhOptimisedSolveUncancellable(n, k, eh_state, solns);
|
EhOptimisedSolveUncancellable(n, k, eh_state,
|
||||||
|
[](std::vector<eh_index> soln) { return false; });
|
||||||
return timer_stop();
|
return timer_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user