Use template parameters to statically initialise Equihash

This commit is contained in:
Jack Grigg 2016-05-05 15:00:44 +12:00
parent 39f5cb35f9
commit e95747288a
7 changed files with 124 additions and 75 deletions

View File

@ -19,31 +19,18 @@
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
void validate_params(int n, int k) template<unsigned int N, unsigned int K>
{ int Equihash<N,K>::InitialiseState(eh_HashState& base_state)
if (k>=n) {
std::cerr << "n must be larger than k\n";
throw invalid_params();
}
if (n % 8 != 0) {
std::cerr << "Parameters must satisfy n = 0 mod 8\n";
throw invalid_params();
}
if ((n/(k+1)) % 8 != 0) {
std::cerr << "Parameters must satisfy n/(k+1) = 0 mod 8\n";
throw invalid_params();
}
}
int Equihash::InitialiseState(eh_HashState& base_state)
{ {
unsigned int n = N;
unsigned int k = K;
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {}; unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
memcpy(personalization, "ZcashPOW", 8); memcpy(personalization, "ZcashPOW", 8);
memcpy(personalization+8, &n, 4); memcpy(personalization+8, &n, 4);
memcpy(personalization+12, &k, 4); memcpy(personalization+12, &k, 4);
return crypto_generichash_blake2b_init_salt_personal(&base_state, return crypto_generichash_blake2b_init_salt_personal(&base_state,
NULL, 0, // No key. NULL, 0, // No key.
n/8, N/8,
NULL, // No salt. NULL, // No salt.
personalization); personalization);
} }
@ -238,27 +225,21 @@ eh_trunc* TruncatedStepRow::GetPartialSolution(eh_index soln_size) const
return p; return p;
} }
Equihash::Equihash(unsigned int n, unsigned int k) : template<unsigned int N, unsigned int K>
n(n), k(k) std::set<std::vector<eh_index>> Equihash<N,K>::BasicSolve(const eh_HashState& base_state)
{ {
validate_params(n, k); eh_index init_size { 1 << (CollisionBitLength + 1) };
}
std::set<std::vector<eh_index>> Equihash::BasicSolve(const eh_HashState& base_state)
{
assert(CollisionBitLength() + 1 < 8*sizeof(eh_index));
eh_index init_size { 1 << (CollisionBitLength() + 1) };
// 1) Generate first list // 1) Generate first list
LogPrint("pow", "Generating first list\n"); LogPrint("pow", "Generating first list\n");
std::vector<FullStepRow> X; std::vector<FullStepRow> X;
X.reserve(init_size); X.reserve(init_size);
for (eh_index i = 0; i < init_size; i++) { for (eh_index i = 0; i < init_size; i++) {
X.emplace_back(n, base_state, i); X.emplace_back(N, base_state, i);
} }
// 3) Repeat step 2 until 2n/(k+1) bits remain // 3) Repeat step 2 until 2n/(k+1) bits remain
for (int r = 1; r < k && X.size() > 0; r++) { for (int r = 1; r < K && X.size() > 0; r++) {
LogPrint("pow", "Round %d:\n", r); LogPrint("pow", "Round %d:\n", r);
// 2a) Sort the list // 2a) Sort the list
LogPrint("pow", "- Sorting list\n"); LogPrint("pow", "- Sorting list\n");
@ -272,7 +253,7 @@ std::set<std::vector<eh_index>> Equihash::BasicSolve(const eh_HashState& base_st
// 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits // 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits
int j = 1; int j = 1;
while (i+j < X.size() && while (i+j < X.size() &&
HasCollision(X[i], X[i+j], CollisionByteLength())) { HasCollision(X[i], X[i+j], CollisionByteLength)) {
j++; j++;
} }
@ -281,7 +262,7 @@ std::set<std::vector<eh_index>> Equihash::BasicSolve(const eh_HashState& base_st
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.push_back(X[i+l] ^ X[i+m]);
Xc.back().TrimHash(CollisionByteLength()); Xc.back().TrimHash(CollisionByteLength);
} }
} }
} }
@ -383,14 +364,14 @@ void CollideBranches(std::vector<FullStepRow>& X, const unsigned int clen, const
} }
} }
std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& base_state) template<unsigned int N, unsigned int K>
std::set<std::vector<eh_index>> Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state)
{ {
assert(CollisionBitLength() + 1 < 8*sizeof(eh_index)); eh_index init_size { 1 << (CollisionBitLength + 1) };
eh_index init_size { 1 << (CollisionBitLength() + 1) };
// First run the algorithm with truncated indices // First run the algorithm with truncated indices
eh_index soln_size { 1 << k }; eh_index soln_size { 1 << K };
std::vector<eh_trunc*> partialSolns; std::vector<eh_trunc*> partialSolns;
{ {
@ -399,11 +380,11 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
std::vector<TruncatedStepRow> Xt; std::vector<TruncatedStepRow> Xt;
Xt.reserve(init_size); Xt.reserve(init_size);
for (eh_index i = 0; i < init_size; i++) { for (eh_index i = 0; i < init_size; i++) {
Xt.emplace_back(n, base_state, i, CollisionBitLength() + 1); Xt.emplace_back(N, base_state, i, CollisionBitLength + 1);
} }
// 3) Repeat step 2 until 2n/(k+1) bits remain // 3) Repeat step 2 until 2n/(k+1) bits remain
for (int r = 1; r < k && Xt.size() > 0; r++) { for (int r = 1; r < K && Xt.size() > 0; r++) {
LogPrint("pow", "Round %d:\n", r); LogPrint("pow", "Round %d:\n", r);
// 2a) Sort the list // 2a) Sort the list
LogPrint("pow", "- Sorting list\n"); LogPrint("pow", "- Sorting list\n");
@ -417,7 +398,7 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
// 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits // 2b) Find next set of unordered pairs with collisions on the next n/(k+1) bits
int j = 1; int j = 1;
while (i+j < Xt.size() && while (i+j < Xt.size() &&
HasCollision(Xt[i], Xt[i+j], CollisionByteLength())) { HasCollision(Xt[i], Xt[i+j], CollisionByteLength)) {
j++; j++;
} }
@ -426,7 +407,7 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
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.push_back(Xt[i+l] ^ Xt[i+m]);
Xc.back().TrimHash(CollisionByteLength()); Xc.back().TrimHash(CollisionByteLength);
} }
} }
@ -477,7 +458,7 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
// Now for each solution run the algorithm again to recreate the indices // Now for each solution run the algorithm again to recreate the indices
LogPrint("pow", "Culling solutions\n"); LogPrint("pow", "Culling solutions\n");
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 (eh_trunc* partialSoln : partialSolns) { for (eh_trunc* partialSoln : partialSolns) {
// 1) Generate first list of possibilities // 1) Generate first list of possibilities
@ -487,8 +468,8 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
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++) {
eh_index newIndex { UntruncateIndex(partialSoln[i], j, CollisionBitLength() + 1) }; eh_index newIndex { UntruncateIndex(partialSoln[i], j, CollisionBitLength + 1) };
ic.emplace_back(n, base_state, newIndex); ic.emplace_back(N, base_state, newIndex);
} }
X.push_back(ic); X.push_back(ic);
} }
@ -505,7 +486,7 @@ std::set<std::vector<eh_index>> Equihash::OptimisedSolve(const eh_HashState& bas
ic.reserve(X[v].size() + X[v+1].size()); ic.reserve(X[v].size() + X[v+1].size());
ic.insert(ic.end(), X[v+1].begin(), X[v+1].end()); ic.insert(ic.end(), X[v+1].begin(), X[v+1].end());
std::sort(ic.begin(), ic.end()); std::sort(ic.begin(), ic.end());
CollideBranches(ic, CollisionByteLength(), CollisionBitLength() + 1, partialSoln[(1<<r)*v], partialSoln[(1<<r)*(v+1)]); CollideBranches(ic, CollisionByteLength, CollisionBitLength + 1, partialSoln[(1<<r)*v], partialSoln[(1<<r)*(v+1)]);
// 2v) Check if this has become an invalid solution // 2v) Check if this has become an invalid solution
if (ic.size() == 0) if (ic.size() == 0)
@ -535,9 +516,10 @@ deletesolution:
return solns; return solns;
} }
bool Equihash::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln) template<unsigned int N, unsigned int K>
bool Equihash<N,K>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln)
{ {
eh_index soln_size { 1u << k }; eh_index soln_size { 1u << K };
if (soln.size() != soln_size) { if (soln.size() != soln_size) {
LogPrint("pow", "Invalid solution size: %d\n", soln.size()); LogPrint("pow", "Invalid solution size: %d\n", soln.size());
return false; return false;
@ -546,13 +528,13 @@ bool Equihash::IsValidSolution(const eh_HashState& base_state, std::vector<eh_in
std::vector<FullStepRow> X; std::vector<FullStepRow> X;
X.reserve(soln_size); X.reserve(soln_size);
for (eh_index i : soln) { for (eh_index i : soln) {
X.emplace_back(n, base_state, i); X.emplace_back(N, base_state, i);
} }
while (X.size() > 1) { while (X.size() > 1) {
std::vector<FullStepRow> Xc; std::vector<FullStepRow> Xc;
for (int i = 0; i < X.size(); i += 2) { for (int i = 0; i < X.size(); i += 2) {
if (!HasCollision(X[i], X[i+1], CollisionByteLength())) { if (!HasCollision(X[i], X[i+1], CollisionByteLength)) {
LogPrint("pow", "Invalid solution: invalid collision length between StepRows\n"); LogPrint("pow", "Invalid solution: invalid collision length between StepRows\n");
LogPrint("pow", "X[i] = %s\n", X[i].GetHex()); LogPrint("pow", "X[i] = %s\n", X[i].GetHex());
LogPrint("pow", "X[i+1] = %s\n", X[i+1].GetHex()); LogPrint("pow", "X[i+1] = %s\n", X[i+1].GetHex());
@ -567,7 +549,7 @@ bool Equihash::IsValidSolution(const eh_HashState& base_state, std::vector<eh_in
return false; return false;
} }
Xc.push_back(X[i] ^ X[i+1]); Xc.push_back(X[i] ^ X[i+1]);
Xc.back().TrimHash(CollisionByteLength()); Xc.back().TrimHash(CollisionByteLength);
} }
X = Xc; X = Xc;
} }
@ -575,3 +557,15 @@ bool Equihash::IsValidSolution(const eh_HashState& base_state, std::vector<eh_in
assert(X.size() == 1); assert(X.size() == 1);
return X[0].IsZero(); return X[0].IsZero();
} }
// 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);
template std::set<std::vector<eh_index>> Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state);
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);
template std::set<std::vector<eh_index>> Equihash<48,5>::OptimisedSolve(const eh_HashState& base_state);
template bool Equihash<48,5>::IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);

View File

@ -15,12 +15,12 @@
#include <set> #include <set>
#include <vector> #include <vector>
#include <boost/static_assert.hpp>
typedef crypto_generichash_blake2b_state eh_HashState; typedef crypto_generichash_blake2b_state eh_HashState;
typedef uint32_t eh_index; typedef uint32_t eh_index;
typedef uint8_t eh_trunc; typedef uint8_t eh_trunc;
struct invalid_params { };
class StepRow class StepRow
{ {
protected: protected:
@ -96,17 +96,20 @@ public:
} }
}; };
template<unsigned int N, unsigned int K>
class Equihash class Equihash
{ {
private: private:
unsigned int n; BOOST_STATIC_ASSERT(K < N);
unsigned int k; BOOST_STATIC_ASSERT(N % 8 == 0);
BOOST_STATIC_ASSERT((N/(K+1)) % 8 == 0);
BOOST_STATIC_ASSERT((N/(K+1)) + 1 < 8*sizeof(eh_index));
public: public:
Equihash(unsigned int n, unsigned int k); enum { CollisionBitLength=N/(K+1) };
enum { CollisionByteLength=CollisionBitLength/8 };
inline unsigned int CollisionBitLength() { return n/(k+1); } Equihash() { }
inline unsigned int CollisionByteLength() { return CollisionBitLength()/8; }
int InitialiseState(eh_HashState& base_state); int InitialiseState(eh_HashState& base_state);
std::set<std::vector<eh_index>> BasicSolve(const eh_HashState& base_state); std::set<std::vector<eh_index>> BasicSolve(const eh_HashState& base_state);
@ -114,4 +117,43 @@ public:
bool IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln); bool IsValidSolution(const eh_HashState& base_state, std::vector<eh_index> soln);
}; };
static Equihash<96,5> Eh965;
static Equihash<48,5> Eh485;
#define EhInitialiseState(n, k, base_state) \
if (n == 96 && k == 5) { \
Eh965.InitialiseState(base_state); \
} else if (n == 48 && k == 5) { \
Eh485.InitialiseState(base_state); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
}
#define EhBasicSolve(n, k, base_state, solns) \
if (n == 96 && k == 5) { \
solns = Eh965.BasicSolve(base_state); \
} else if (n == 48 && k == 5) { \
solns = Eh485.BasicSolve(base_state); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
}
#define EhOptimisedSolve(n, k, base_state, solns) \
if (n == 96 && k == 5) { \
solns = Eh965.OptimisedSolve(base_state); \
} else if (n == 48 && k == 5) { \
solns = Eh485.OptimisedSolve(base_state); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
}
#define EhIsValidSolution(n, k, base_state, soln, ret) \
if (n == 96 && k == 5) { \
ret = Eh965.IsValidSolution(base_state, soln); \
} else if (n == 48 && k == 5) { \
ret = Eh485.IsValidSolution(base_state, soln); \
} else { \
throw std::invalid_argument("Unsupported Equihash parameters"); \
}
#endif // BITCOIN_EQUIHASH_H #endif // BITCOIN_EQUIHASH_H

View File

@ -443,7 +443,8 @@ void static BitcoinMiner(CWallet *pwallet)
CReserveKey reservekey(pwallet); CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0; unsigned int nExtraNonce = 0;
Equihash eh {chainparams.EquihashN(), chainparams.EquihashK()}; unsigned int n = chainparams.EquihashN();
unsigned int k = chainparams.EquihashK();
try { try {
while (true) { while (true) {
@ -489,7 +490,7 @@ void static BitcoinMiner(CWallet *pwallet)
while (true) { while (true) {
// Hash state // Hash state
crypto_generichash_blake2b_state state; crypto_generichash_blake2b_state state;
eh.InitialiseState(state); EhInitialiseState(n, k, state);
// I = the block header minus nonce and solution. // I = the block header minus nonce and solution.
CEquihashInput I{*pblock}; CEquihashInput I{*pblock};
@ -512,7 +513,8 @@ 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 = eh.BasicSolve(curr_state); std::set<std::vector<unsigned int>> solns;
EhBasicSolve(n, k, curr_state, solns);
LogPrint("pow", "Solutions: %d\n", solns.size()); LogPrint("pow", "Solutions: %d\n", solns.size());
// Write the solution to the hash and compute the result. // Write the solution to the hash and compute the result.

View File

@ -88,11 +88,12 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params) bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
{ {
Equihash eh {params.EquihashN(), params.EquihashK()}; unsigned int n = params.EquihashN();
unsigned int k = params.EquihashK();
// Hash state // Hash state
crypto_generichash_blake2b_state state; crypto_generichash_blake2b_state state;
eh.InitialiseState(state); EhInitialiseState(n, k, state);
// I = the block header minus nonce and solution. // I = the block header minus nonce and solution.
CEquihashInput I{*pblock}; CEquihashInput I{*pblock};
@ -104,7 +105,9 @@ bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& param
// H(I||V||... // H(I||V||...
crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size()); crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
if (!eh.IsValidSolution(state, pblock->nSolution)) bool isValid;
EhIsValidSolution(n, k, state, pblock->nSolution, isValid);
if (!isValid)
return error("CheckEquihashSolution(): invalid solution"); return error("CheckEquihashSolution(): invalid solution");
return true; return true;

View File

@ -150,7 +150,8 @@ Value generate(const Array& params, bool fHelp)
} }
unsigned int nExtraNonce = 0; unsigned int nExtraNonce = 0;
Array blockHashes; Array blockHashes;
Equihash eh {Params().EquihashN(), Params().EquihashK()}; unsigned int n = Params().EquihashN();
unsigned int k = Params().EquihashK();
while (nHeight < nHeightEnd) while (nHeight < nHeightEnd)
{ {
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey)); auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
@ -164,7 +165,7 @@ Value generate(const Array& params, bool fHelp)
// Hash state // Hash state
crypto_generichash_blake2b_state eh_state; crypto_generichash_blake2b_state eh_state;
eh.InitialiseState(eh_state); EhInitialiseState(n, k, eh_state);
// I = the block header minus nonce and solution. // I = the block header minus nonce and solution.
CEquihashInput I{*pblock}; CEquihashInput I{*pblock};
@ -187,10 +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 = eh.BasicSolve(curr_state); std::set<std::vector<unsigned int>> solns;
EhBasicSolve(n, k, curr_state, solns);
for (auto soln : solns) { for (auto soln : solns) {
assert(eh.IsValidSolution(curr_state, soln)); bool isValid;
EhIsValidSolution(n, k, curr_state, soln, isValid);
assert(isValid);
pblock->nSolution = soln; pblock->nSolution = soln;
if (CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) { if (CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {

View File

@ -41,16 +41,16 @@ void PrintSolutions(std::stringstream &strm, std::set<std::vector<uint32_t>> sol
} }
void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, const std::set<std::vector<uint32_t>> &solns) { void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, const std::set<std::vector<uint32_t>> &solns) {
Equihash eh {n, k};
crypto_generichash_blake2b_state state; crypto_generichash_blake2b_state state;
eh.InitialiseState(state); EhInitialiseState(n, k, state);
uint256 V = ArithToUint256(nonce); uint256 V = ArithToUint256(nonce);
BOOST_TEST_MESSAGE("Running solver: n = " << n << ", k = " << k << ", I = " << I << ", V = " << V.GetHex()); BOOST_TEST_MESSAGE("Running solver: n = " << n << ", k = " << k << ", I = " << I << ", V = " << V.GetHex());
crypto_generichash_blake2b_update(&state, (unsigned char*)&I[0], I.size()); crypto_generichash_blake2b_update(&state, (unsigned char*)&I[0], I.size());
crypto_generichash_blake2b_update(&state, V.begin(), V.size()); crypto_generichash_blake2b_update(&state, V.begin(), V.size());
// First test the basic solver // First test the basic solver
std::set<std::vector<uint32_t>> ret = eh.BasicSolve(state); std::set<std::vector<uint32_t>> ret;
EhBasicSolve(n, k, state, ret);
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);
@ -58,7 +58,8 @@ void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, c
BOOST_CHECK(ret == solns); BOOST_CHECK(ret == solns);
// 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 = eh.OptimisedSolve(state); std::set<std::vector<uint32_t>> retOpt;
EhOptimisedSolve(n, k, state, retOpt);
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);
@ -68,9 +69,8 @@ void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, c
} }
void TestEquihashValidator(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, std::vector<uint32_t> soln, bool expected) { void TestEquihashValidator(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, std::vector<uint32_t> soln, bool expected) {
Equihash eh {n, k};
crypto_generichash_blake2b_state state; crypto_generichash_blake2b_state state;
eh.InitialiseState(state); EhInitialiseState(n, k, state);
uint256 V = ArithToUint256(nonce); uint256 V = ArithToUint256(nonce);
crypto_generichash_blake2b_update(&state, (unsigned char*)&I[0], I.size()); crypto_generichash_blake2b_update(&state, (unsigned char*)&I[0], I.size());
crypto_generichash_blake2b_update(&state, V.begin(), V.size()); crypto_generichash_blake2b_update(&state, V.begin(), V.size());
@ -78,7 +78,9 @@ void TestEquihashValidator(unsigned int n, unsigned int k, const std::string &I,
std::stringstream strm; std::stringstream strm;
PrintSolution(strm, soln); PrintSolution(strm, soln);
BOOST_TEST_MESSAGE(strm.str()); BOOST_TEST_MESSAGE(strm.str());
BOOST_CHECK(eh.IsValidSolution(state, soln) == expected); bool isValid;
EhIsValidSolution(n, k, state, soln, isValid);
BOOST_CHECK(isValid == expected);
} }
BOOST_AUTO_TEST_CASE(solver_testvectors) { BOOST_AUTO_TEST_CASE(solver_testvectors) {

View File

@ -100,9 +100,10 @@ double benchmark_solve_equihash()
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << I; ss << I;
Equihash eh {Params(CBaseChainParams::MAIN).EquihashN(), Params(CBaseChainParams::MAIN).EquihashK()}; unsigned int n = Params(CBaseChainParams::MAIN).EquihashN();
unsigned int k = Params(CBaseChainParams::MAIN).EquihashK();
crypto_generichash_blake2b_state eh_state; crypto_generichash_blake2b_state eh_state;
eh.InitialiseState(eh_state); EhInitialiseState(n, k, eh_state);
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
uint256 nonce; uint256 nonce;
@ -112,7 +113,8 @@ double benchmark_solve_equihash()
nonce.size()); nonce.size());
timer_start(); timer_start();
eh.BasicSolve(eh_state); std::set<std::vector<unsigned int>> solns;
EhBasicSolve(n, k, eh_state, solns);
return timer_stop(); return timer_stop();
} }