Use Equihash for Proof-of-Work

The main and test networks are configured to use parameters that are currently
low-memory but usable with the basic solver; they will be increased once the
solver is optimised. The regtest network is configured to have extremely low
memory usage for speed.

Note that Bitcoin's double-hasher is used for the difficulty check. This does
not match the paper, but is simpler than changing the block header
serialization. Single hashing is kept for the EquiHash solver because there is
no requirement on execution time there, only on memory usage.
This commit is contained in:
Jack Grigg
2016-02-28 20:19:07 +00:00
parent 020bed6021
commit fdda3c5085
13 changed files with 200 additions and 70 deletions

View File

@@ -7,10 +7,15 @@
#include "arith_uint256.h"
#include "chain.h"
#include "chainparams.h"
#include "crypto/equihash.h"
#include "primitives/block.h"
#include "streams.h"
#include "uint256.h"
#include "util.h"
#include "sodium.h"
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
@@ -81,6 +86,30 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
return bnNew.GetCompact();
}
bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
{
Equihash eh {params.EquihashN(), params.EquihashK()};
// Hash state
crypto_generichash_blake2b_state state;
eh.InitialiseState(state);
// I = the block header minus nonce and solution.
CEquihashInput I{*pblock};
// I||V
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << I;
ss << pblock->nNonce;
// H(I||V||...
crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
if (!eh.IsValidSolution(state, pblock->nSolution))
return error("CheckEquihashSolution(): invalid solution");
return true;
}
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
bool fNegative;