diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 46d40784b..eaf16d61a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -3,7 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chainparams.h" +#include "main.h" +#include "crypto/equihash.h" #include "util.h" #include "utilstrencodings.h" @@ -59,8 +60,10 @@ public: nMinerThreads = 0; nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 100000; - nEquihashN = 200; - nEquihashK = 9; + const size_t N = 200, K = 9; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + nEquihashN = N; + nEquihashK = K; /** * Build the genesis block. Note that the output of its generation @@ -222,8 +225,10 @@ public: pchMessageStart[3] = 0x5f; nMinerThreads = 1; nMaxTipAge = 24 * 60 * 60; - nEquihashN = 48; - nEquihashK = 5; + const size_t N = 48, K = 5; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + nEquihashN = N; + nEquihashK = K; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000002"); diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index f56f367dd..523f18c45 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -419,10 +419,12 @@ bool Equihash::BasicSolve(const eh_HashState& base_state, for (int l = 0; l < j - 1; l++) { for (int m = l + 1; m < j; m++) { FullStepRow res(X[i+l], X[i+m], hashLen, lenIndices, 0); - if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices) && - validBlock(res.GetIndices(hashLen, 2*lenIndices, - CollisionBitLength))) { - return true; + if (DistinctIndices(X[i+l], X[i+m], hashLen, lenIndices)) { + auto soln = res.GetIndices(hashLen, 2*lenIndices, CollisionBitLength); + assert(soln.size() == equihash_solution_size(N, K)); + if (validBlock(soln)) { + return true; + } } } } @@ -691,7 +693,9 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, // We are at the top of the tree assert(X.size() == K+1); for (FullStepRow row : *X[K]) { - solns.insert(row.GetIndices(hashLen, lenIndices, CollisionBitLength)); + auto soln = row.GetIndices(hashLen, lenIndices, CollisionBitLength); + assert(soln.size() == equihash_solution_size(N, K)); + solns.insert(soln); } for (auto soln : solns) { if (validBlock(soln)) diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 43401b590..3f1c300b9 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -155,6 +155,10 @@ class EhSolverCancelledException : public std::exception inline constexpr const size_t max(const size_t A, const size_t B) { return A > B ? A : B; } +inline constexpr size_t equihash_solution_size(unsigned int N, unsigned int K) { + return (1 << K)*(N/(K+1)+1)/8; +} + template class Equihash { diff --git a/src/gtest/test_block.cpp b/src/gtest/test_block.cpp new file mode 100644 index 000000000..a0cdc1162 --- /dev/null +++ b/src/gtest/test_block.cpp @@ -0,0 +1,13 @@ +#include + +#include "primitives/block.h" + + +TEST(block_tests, header_size_is_expected) { + // Dummy header with an empty Equihash solution. + CBlockHeader header; + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << header; + + ASSERT_EQ(ss.size(), CBlockHeader::HEADER_SIZE); +} diff --git a/src/main.h b/src/main.h index 2ce1a5575..7a3057867 100644 --- a/src/main.h +++ b/src/main.h @@ -94,6 +94,10 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; /** Maximum length of reject messages. */ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; +#define equihash_parameters_acceptable(N, K) \ + ((CBlockHeader::HEADER_SIZE + equihash_solution_size(N, K))*MAX_HEADERS_RESULTS < \ + MAX_PROTOCOL_MESSAGE_LENGTH-1000) + struct BlockHasher { size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); } diff --git a/src/primitives/block.h b/src/primitives/block.h index 1e83225d2..6180fb2ae 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -21,6 +21,7 @@ class CBlockHeader { public: // header + static const size_t HEADER_SIZE=4+32+32+32+4+4+32; // excluding Equihash solution static const int32_t CURRENT_VERSION=4; int32_t nVersion; uint256 hashPrevBlock;