@ -18,9 +18,12 @@
# include "util.h"
# include "utilmoneystr.h"
# ifdef ENABLE_WALLET
# include "crypto/equihash.h"
# include "wallet/wallet.h"
# endif
# include "sodium.h"
# include <boost/thread.hpp>
# include <boost/tuple/tuple.hpp>
@ -338,7 +341,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
pblock - > hashPrevBlock = pindexPrev - > GetBlockHash ( ) ;
UpdateTime ( pblock , Params ( ) . GetConsensus ( ) , pindexPrev ) ;
pblock - > nBits = GetNextWorkRequired ( pindexPrev , pblock , Params ( ) . GetConsensus ( ) ) ;
pblock - > nNonce = 0 ;
pblock - > nNonce = uint256 ( ) ;
pblock - > nSolution . clear ( ) ;
pblocktemplate - > vTxSigOps [ 0 ] = GetLegacySigOpCount ( pblock - > vtx [ 0 ] ) ;
CValidationState state ;
@ -374,39 +378,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
// Internal miner
//
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
// The nonce is usually preserved between calls, but periodically or if the
// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
// zero.
//
bool static ScanHash ( const CBlockHeader * pblock , uint32_t & nNonce , uint256 * phash )
{
// Write the first 76 bytes of the block header to a double-SHA256 state.
CHash256 hasher ;
CDataStream ss ( SER_NETWORK , PROTOCOL_VERSION ) ;
ss < < * pblock ;
assert ( ss . size ( ) = = 80 ) ;
hasher . Write ( ( unsigned char * ) & ss [ 0 ] , 76 ) ;
while ( true ) {
nNonce + + ;
// Write the last 4 bytes of the block header (the nonce) to a copy of
// the double-SHA256 state, and compute the result.
CHash256 ( hasher ) . Write ( ( unsigned char * ) & nNonce , 4 ) . Finalize ( ( unsigned char * ) phash ) ;
// Return the nonce if the hash has at least some zero bits,
// caller will check if it has enough to reach the target
if ( ( ( uint16_t * ) phash ) [ 15 ] = = 0 )
return true ;
// If nothing found after trying for a while, return -1
if ( ( nNonce & 0xfff ) = = 0 )
return false ;
}
}
CBlockTemplate * CreateNewBlockWithKey ( CReserveKey & reservekey )
{
CPubKey pubkey ;
@ -426,7 +397,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
{
LOCK ( cs_main ) ;
if ( pblock - > hashPrevBlock ! = chainActive . Tip ( ) - > GetBlockHash ( ) )
return error ( " Bitcoin Miner: generated block is stale" ) ;
return error ( " Zcash Miner: generated block is stale" ) ;
}
// Remove key from key pool
@ -441,22 +412,24 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
// Process this block the same as if we had received it from another node
CValidationState state ;
if ( ! ProcessNewBlock ( state , NULL , pblock , true , NULL ) )
return error ( " Bitcoin Miner: ProcessNewBlock, block not accepted" ) ;
return error ( " Zcash Miner: ProcessNewBlock, block not accepted" ) ;
return true ;
}
void static BitcoinMiner ( CWallet * pwallet )
{
LogPrintf ( " Bitcoin Miner started\n " ) ;
LogPrintf ( " Zcash Miner started\n " ) ;
SetThreadPriority ( THREAD_PRIORITY_LOWEST ) ;
RenameThread ( " bitcoin -miner" ) ;
RenameThread ( " zcash -miner" ) ;
const CChainParams & chainparams = Params ( ) ;
// Each thread has its own key and counter
CReserveKey reservekey ( pwallet ) ;
unsigned int nExtraNonce = 0 ;
Equihash eh { chainparams . EquihashN ( ) , chainparams . EquihashK ( ) } ;
try {
while ( true ) {
if ( chainparams . MiningRequiresPeers ( ) ) {
@ -483,13 +456,13 @@ void static BitcoinMiner(CWallet *pwallet)
auto_ptr < CBlockTemplate > pblocktemplate ( CreateNewBlockWithKey ( reservekey ) ) ;
if ( ! pblocktemplate . get ( ) )
{
LogPrintf ( " Error in Bitcoin Miner: Keypool ran out, please call keypoolrefill before restarting the mining thread \n " ) ;
LogPrintf ( " Error in Zcash Miner: Keypool ran out, please call keypoolrefill before restarting the mining thread \n " ) ;
return ;
}
CBlock * pblock = & pblocktemplate - > block ;
IncrementExtraNonce ( pblock , pindexPrev , nExtraNonce ) ;
LogPrintf ( " Running Bitcoin Miner with %u transactions in block (%u bytes) \n " , pblock - > vtx . size ( ) ,
LogPrintf ( " Running Zcash Miner with %u transactions in block (%u bytes) \n " , pblock - > vtx . size ( ) ,
: : GetSerializeSize ( * pblock , SER_NETWORK , PROTOCOL_VERSION ) ) ;
//
@ -497,21 +470,48 @@ void static BitcoinMiner(CWallet *pwallet)
//
int64_t nStart = GetTime ( ) ;
arith_uint256 hashTarget = arith_uint256 ( ) . SetCompact ( pblock - > nBits ) ;
uint256 hash ;
uint32_t nNonce = 0 ;
// Hash state
crypto_generichash_blake2b_state state ;
eh . InitialiseState ( state ) ;
// I = the block header minus nonce and solution.
CEquihashInput I { * pblock } ;
CDataStream ss ( SER_NETWORK , PROTOCOL_VERSION ) ;
ss < < I ;
// H(I||...
crypto_generichash_blake2b_update ( & state , ( unsigned char * ) & ss [ 0 ] , ss . size ( ) ) ;
while ( true ) {
// Check if something found
if ( ScanHash ( pblock , nNonce , & hash ) )
// Find valid nonce
while ( true )
{
if ( UintToArith256 ( hash ) < = hashTarget )
{
// Found a solution
pblock - > nNonce = nNonce ;
assert ( hash = = pblock - > GetHash ( ) ) ;
// H(I||V||...
crypto_generichash_blake2b_state curr_state ;
curr_state = state ;
crypto_generichash_blake2b_update ( & curr_state ,
pblock - > nNonce . begin ( ) ,
pblock - > nNonce . size ( ) ) ;
// (x_1, x_2, ...) = A(I, V, n, k)
LogPrint ( " pow " , " Running Equihash solver with nNonce = %s \n " ,
pblock - > nNonce . ToString ( ) ) ;
std : : set < std : : vector < unsigned int > > solns = eh . BasicSolve ( curr_state ) ;
LogPrint ( " pow " , " Solutions: %d \n " , solns . size ( ) ) ;
// Write the solution to the hash and compute the result.
for ( auto soln : solns ) {
pblock - > nSolution = soln ;
if ( UintToArith256 ( pblock - > GetHash ( ) ) > hashTarget ) {
continue ;
}
// Found a solution
SetThreadPriority ( THREAD_PRIORITY_NORMAL ) ;
LogPrintf ( " BitcoinMiner: \n " ) ;
LogPrintf ( " proof-of-work found \n hash: %s \n target: %s \n " , hash . GetHex ( ) , hashTarget . GetHex ( ) ) ;
LogPrintf ( " Zcash Miner:\n " ) ;
LogPrintf ( " proof-of-work found \n hash: %s \n target: %s \n " , pblock - > GetHash ( ) . GetHex ( ) , hashTarget . GetHex ( ) ) ;
ProcessBlockFound ( pblock , * pwallet , reservekey ) ;
SetThreadPriority ( THREAD_PRIORITY_LOWEST ) ;
@ -519,16 +519,20 @@ void static BitcoinMiner(CWallet *pwallet)
if ( chainparams . MineBlocksOnDemand ( ) )
throw boost : : thread_interrupted ( ) ;
brea k;
goto updatebloc k;
}
pblock - > nNonce = ArithToUint256 ( UintToArith256 ( pblock - > nNonce ) + 1 ) ;
if ( ( UintToArith256 ( pblock - > nNonce ) & 0x1 ) = = 0 )
break ;
}
updateblock :
// Check for stop or if block needs to be rebuilt
boost : : this_thread : : interruption_point ( ) ;
// Regtest mode doesn't require peers
if ( vNodes . empty ( ) & & chainparams . MiningRequiresPeers ( ) )
break ;
if ( nNonce > = 0xffff0000 )
if ( UintToArith256 ( pblock - > nNonce ) > = 0xffff )
break ;
if ( mempool . GetTransactionsUpdated ( ) ! = nTransactionsUpdatedLast & & GetTime ( ) - nStart > 60 )
break ;
@ -547,12 +551,12 @@ void static BitcoinMiner(CWallet *pwallet)
}
catch ( const boost : : thread_interrupted & )
{
LogPrintf ( " Bitcoin Miner terminated\n " ) ;
LogPrintf ( " Zcash Miner terminated\n " ) ;
throw ;
}
catch ( const std : : runtime_error & e )
{
LogPrintf ( " Bitcoin Miner runtime error: %s\n " , e . what ( ) ) ;
LogPrintf ( " Zcash Miner runtime error: %s\n " , e . what ( ) ) ;
return ;
}
}