Add mostly-static checks on consistency of Equihash parameters, MAX_HEADERS_RESULTS, and MAX_PROTOCOL_MESSAGE_LENGTH.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
@@ -3,7 +3,8 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// 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 "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
@@ -59,8 +60,10 @@ public:
|
|||||||
nMinerThreads = 0;
|
nMinerThreads = 0;
|
||||||
nMaxTipAge = 24 * 60 * 60;
|
nMaxTipAge = 24 * 60 * 60;
|
||||||
nPruneAfterHeight = 100000;
|
nPruneAfterHeight = 100000;
|
||||||
nEquihashN = 200;
|
const size_t N = 200, K = 9;
|
||||||
nEquihashK = 9;
|
BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K));
|
||||||
|
nEquihashN = N;
|
||||||
|
nEquihashK = K;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the genesis block. Note that the output of its generation
|
* Build the genesis block. Note that the output of its generation
|
||||||
@@ -222,8 +225,10 @@ public:
|
|||||||
pchMessageStart[3] = 0x5f;
|
pchMessageStart[3] = 0x5f;
|
||||||
nMinerThreads = 1;
|
nMinerThreads = 1;
|
||||||
nMaxTipAge = 24 * 60 * 60;
|
nMaxTipAge = 24 * 60 * 60;
|
||||||
nEquihashN = 48;
|
const size_t N = 48, K = 5;
|
||||||
nEquihashK = 5;
|
BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K));
|
||||||
|
nEquihashN = N;
|
||||||
|
nEquihashK = K;
|
||||||
genesis.nTime = 1296688602;
|
genesis.nTime = 1296688602;
|
||||||
genesis.nBits = 0x207fffff;
|
genesis.nBits = 0x207fffff;
|
||||||
genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000002");
|
genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000002");
|
||||||
|
|||||||
@@ -419,10 +419,12 @@ bool Equihash<N,K>::BasicSolve(const eh_HashState& base_state,
|
|||||||
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)) {
|
||||||
validBlock(res.GetIndices(hashLen, 2*lenIndices,
|
auto soln = res.GetIndices(hashLen, 2*lenIndices, CollisionBitLength);
|
||||||
CollisionBitLength))) {
|
assert(soln.size() == equihash_solution_size(N, K));
|
||||||
return true;
|
if (validBlock(soln)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -691,7 +693,9 @@ bool Equihash<N,K>::OptimisedSolve(const eh_HashState& base_state,
|
|||||||
// 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, CollisionBitLength));
|
auto soln = row.GetIndices(hashLen, lenIndices, CollisionBitLength);
|
||||||
|
assert(soln.size() == equihash_solution_size(N, K));
|
||||||
|
solns.insert(soln);
|
||||||
}
|
}
|
||||||
for (auto soln : solns) {
|
for (auto soln : solns) {
|
||||||
if (validBlock(soln))
|
if (validBlock(soln))
|
||||||
|
|||||||
@@ -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 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<unsigned int N, unsigned int K>
|
template<unsigned int N, unsigned int K>
|
||||||
class Equihash
|
class Equihash
|
||||||
{
|
{
|
||||||
|
|||||||
13
src/gtest/test_block.cpp
Normal file
13
src/gtest/test_block.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -94,6 +94,10 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
|
|||||||
/** Maximum length of reject messages. */
|
/** Maximum length of reject messages. */
|
||||||
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
|
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
|
struct BlockHasher
|
||||||
{
|
{
|
||||||
size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
|
size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class CBlockHeader
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// header
|
// header
|
||||||
|
static const size_t HEADER_SIZE=4+32+32+32+4+4+32; // excluding Equihash solution
|
||||||
static const int32_t CURRENT_VERSION=4;
|
static const int32_t CURRENT_VERSION=4;
|
||||||
int32_t nVersion;
|
int32_t nVersion;
|
||||||
uint256 hashPrevBlock;
|
uint256 hashPrevBlock;
|
||||||
|
|||||||
Reference in New Issue
Block a user