|
|
@ -4026,22 +4026,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// BitcoinMiner
|
|
|
|
// LitecoinMiner
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
int static FormatHashBlocks(void* pbuffer, unsigned int len) |
|
|
|
int static FormatHashBlocks(void* pbuffer, unsigned int len) |
|
|
@ -4448,7 +4435,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
//// debug print
|
|
|
|
//// debug print
|
|
|
|
printf("BitcoinMiner:\n"); |
|
|
|
printf("Litecoin RPCMiner:\n"); |
|
|
|
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str()); |
|
|
|
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str()); |
|
|
|
pblock->print(); |
|
|
|
pblock->print(); |
|
|
|
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); |
|
|
|
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); |
|
|
@ -4457,7 +4444,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_main); |
|
|
|
LOCK(cs_main); |
|
|
|
if (pblock->hashPrevBlock != hashBestChain) |
|
|
|
if (pblock->hashPrevBlock != hashBestChain) |
|
|
|
return error("BitcoinMiner : generated block is stale"); |
|
|
|
return error("LitecoinMiner : generated block is stale"); |
|
|
|
|
|
|
|
|
|
|
|
// Remove key from key pool
|
|
|
|
// Remove key from key pool
|
|
|
|
reservekey.KeepKey(); |
|
|
|
reservekey.KeepKey(); |
|
|
@ -4471,165 +4458,12 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) |
|
|
|
// Process this block the same as if we had received it from another node
|
|
|
|
// Process this block the same as if we had received it from another node
|
|
|
|
CValidationState state; |
|
|
|
CValidationState state; |
|
|
|
if (!ProcessBlock(state, NULL, pblock)) |
|
|
|
if (!ProcessBlock(state, NULL, pblock)) |
|
|
|
return error("BitcoinMiner : ProcessBlock, block not accepted"); |
|
|
|
return error("LitecoinMiner : ProcessBlock, block not accepted"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void static BitcoinMiner(CWallet *pwallet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("BitcoinMiner started\n"); |
|
|
|
|
|
|
|
SetThreadPriority(THREAD_PRIORITY_LOWEST); |
|
|
|
|
|
|
|
RenameThread("bitcoin-miner"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Each thread has its own key and counter
|
|
|
|
|
|
|
|
CReserveKey reservekey(pwallet); |
|
|
|
|
|
|
|
unsigned int nExtraNonce = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { loop { |
|
|
|
|
|
|
|
while (vNodes.empty()) |
|
|
|
|
|
|
|
MilliSleep(1000); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Create new block
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated; |
|
|
|
|
|
|
|
CBlockIndex* pindexPrev = pindexBest; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(reservekey)); |
|
|
|
|
|
|
|
if (!pblocktemplate.get()) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
CBlock *pblock = &pblocktemplate->block; |
|
|
|
|
|
|
|
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(), |
|
|
|
|
|
|
|
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Pre-build hash buffers
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf); |
|
|
|
|
|
|
|
char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf); |
|
|
|
|
|
|
|
char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FormatHashBuffers(pblock, pmidstate, pdata, phash1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4); |
|
|
|
|
|
|
|
unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8); |
|
|
|
|
|
|
|
unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Search
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
int64 nStart = GetTime(); |
|
|
|
|
|
|
|
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); |
|
|
|
|
|
|
|
loop |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
unsigned int nHashesDone = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint256 thash; |
|
|
|
|
|
|
|
char scratchpad[SCRYPT_SCRATCHPAD_SIZE]; |
|
|
|
|
|
|
|
loop |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
scrypt_1024_1_1_256_sp(BEGIN(pblock->nVersion), BEGIN(thash), scratchpad); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (thash <= hashTarget) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Found a solution
|
|
|
|
|
|
|
|
SetThreadPriority(THREAD_PRIORITY_NORMAL); |
|
|
|
|
|
|
|
CheckWork(pblock, *pwalletMain, reservekey); |
|
|
|
|
|
|
|
SetThreadPriority(THREAD_PRIORITY_LOWEST); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
pblock->nNonce += 1; |
|
|
|
|
|
|
|
nHashesDone += 1; |
|
|
|
|
|
|
|
if ((pblock->nNonce & 0xFF) == 0) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Meter hashes/sec
|
|
|
|
|
|
|
|
static int64 nHashCounter; |
|
|
|
|
|
|
|
if (nHPSTimerStart == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
nHPSTimerStart = GetTimeMillis(); |
|
|
|
|
|
|
|
nHashCounter = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
nHashCounter += nHashesDone; |
|
|
|
|
|
|
|
if (GetTimeMillis() - nHPSTimerStart > 4000) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
static CCriticalSection cs; |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOCK(cs); |
|
|
|
|
|
|
|
if (GetTimeMillis() - nHPSTimerStart > 4000) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); |
|
|
|
|
|
|
|
nHPSTimerStart = GetTimeMillis(); |
|
|
|
|
|
|
|
nHashCounter = 0; |
|
|
|
|
|
|
|
static int64 nLogTime; |
|
|
|
|
|
|
|
if (GetTime() - nLogTime > 30 * 60) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
nLogTime = GetTime(); |
|
|
|
|
|
|
|
printf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check for stop or if block needs to be rebuilt
|
|
|
|
|
|
|
|
boost::this_thread::interruption_point(); |
|
|
|
|
|
|
|
if (vNodes.empty()) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
if (pblock->nNonce >= 0xffff0000) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
if (pindexPrev != pindexBest) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update nTime every few seconds
|
|
|
|
|
|
|
|
pblock->UpdateTime(pindexPrev); |
|
|
|
|
|
|
|
nBlockTime = ByteReverse(pblock->nTime); |
|
|
|
|
|
|
|
if (fTestNet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Changing pblock->nTime can change work required on testnet:
|
|
|
|
|
|
|
|
nBlockBits = ByteReverse(pblock->nBits); |
|
|
|
|
|
|
|
hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} } |
|
|
|
|
|
|
|
catch (boost::thread_interrupted) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
printf("BitcoinMiner terminated\n"); |
|
|
|
|
|
|
|
throw; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void GenerateBitcoins(bool fGenerate, CWallet* pwallet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
static boost::thread_group* minerThreads = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int nThreads = GetArg("-genproclimit", -1); |
|
|
|
|
|
|
|
if (nThreads < 0) |
|
|
|
|
|
|
|
nThreads = boost::thread::hardware_concurrency(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (minerThreads != NULL) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
minerThreads->interrupt_all(); |
|
|
|
|
|
|
|
delete minerThreads; |
|
|
|
|
|
|
|
minerThreads = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nThreads == 0 || !fGenerate) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
minerThreads = new boost::thread_group(); |
|
|
|
|
|
|
|
for (int i = 0; i < nThreads; i++) |
|
|
|
|
|
|
|
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Amount compression:
|
|
|
|
// Amount compression:
|
|
|
|
// * If the amount is 0, output 0
|
|
|
|
// * If the amount is 0, output 0
|
|
|
|
// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
|
|
|
|
// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
|
|
|
|