Я имею в виду если будет сделан NMC-2 клиент для народа на scrypt
чтобы он все делал по понятиям как в пдфке
а не как у TBX.
В TBX копипаст референсной реализации, прикрученный через задницу
* сорри за риторику * Чтобы было нормально, надо исправить функцию GetHash(), а не прикручивать костыли в виде дополнительных функций и проверок...
Вот моя адаптация версии scrypt от pooler'а, пригодная для использования в клиенте:
http://zalil.ru/32646840Для майнинга надо использовать функцию scanhash_scrypt, для получения хэша от переданного массива байтов с указанной длиной функцию scrypt_hash. Я это в своих экспериментах делал вот так:
в файле main.cpp:
#include "scrypt_mine.h"
<...//..>
void static BitcoinMiner(CWallet *pwallet, int thread_id)
{
printf("Miner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
// Each thread has its own key and counter
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
void *scratchbuf = scrypt_buffer_alloc();
while (fGenerateBitcoins)
{
if (AffinityBugWorkaround(ThreadMiner))
return;
if (fShutdown)
return;
while (vNodes.empty() || IsInitialBlockDownload())
{
Sleep(1000);
if (fShutdown)
return;
if (!fGenerateBitcoins)
return;
}
//
// Create new block
//
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
CBlockIndex* pindexPrev = pindexBest;
auto_ptr pblock(CreateNewBlock(pwallet));
if (!pblock.get())
return;
IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce);
printf("Running Miner with %d transactions in block\n", pblock->vtx.size());
//
// Search
//
uint64_t nStart = GetTime();
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
uint32_t max_nonce = 0xffff0000;
block_header res_header;
uint256 result;
loop
{
// Check for stop or if block needs to be rebuilt
if (fShutdown)
return;
if (!fGenerateBitcoins)
return;
if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
return;
if (vNodes.empty())
break;
bool rc = scanhash_scrypt(
(block_header *)&pblock->nVersion, sizeof(block_header), UINTBEGIN(hashTarget),
scratchbuf, max_nonce, &sStat[thread_id - 1], nStart, pindexPrev,
nTransactionsUpdatedLast, UBEGIN(result), &res_header
);
pblock->nNonce = res_header.nonce;
if (rc)
{
static CCriticalSection cs;
CRITICAL_BLOCK(cs)
{
printf("Thread %d: scan hash result = %i, nonce value = %d, hash = %s, target = %s\n", thread_id, rc, pblock->nNonce, result.ToString().c_str(), hashTarget.ToString().c_str());
// Found a solution
SetThreadPriority(THREAD_PRIORITY_NORMAL);
CheckWork(pblock.get(), *pwalletMain, reservekey);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
}
break;
}
else
if( (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60) ||
(pindexPrev != pindexBest)
)
break;
// Update nTime every few seconds
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
}
}
scrypt_buffer_free(scratchbuf);
}
в файле main.h
#include "scrypt_mine.h"
<...//..>
/*
uint256 GetHash() const
{
return Hash(BEGIN(nVersion), END(nNonce));
}*/
uint256 GetHash() const
{
uint256 thash;
void * scratchbuff = scrypt_buffer_alloc();
scrypt_hash(CVOIDBEGIN(nVersion), sizeof(block_header), UINTBEGIN(thash), scratchbuff);
scrypt_buffer_free(scratchbuff);
return thash;
}
CVOIDBEGIN и UINTBEGIN это макросы, определенные по аналогии со штатным BEGIN в файле util.h:
#define UINTBEGIN(a) ((uint32_t*)&(a))
#define CVOIDBEGIN(a) ((const void*)&(a))
Плюс значение переменной bnProofOfWorkLimit надо сделать ~uint256(0) >> 20, потому что по умолчанию оно ориентировано на sha256 И настолько высокое, что со scrypt юзер никогда на такой сложности задачу не решит, имхо.
Если будут вопросы, поясню что как.