Switch miner.cpp to use sha2 instead of OpenSSL.
This commit is contained in:
parent
cf0c47b269
commit
85aab2a088
162
src/miner.cpp
162
src/miner.cpp
@ -6,14 +6,13 @@
|
|||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
#include "hash.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
#include "wallet.h"
|
#include "wallet.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <openssl/sha.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -21,42 +20,6 @@ using namespace std;
|
|||||||
// BitcoinMiner
|
// BitcoinMiner
|
||||||
//
|
//
|
||||||
|
|
||||||
int static FormatHashBlocks(void* pbuffer, unsigned int len)
|
|
||||||
{
|
|
||||||
unsigned char* pdata = (unsigned char*)pbuffer;
|
|
||||||
unsigned int blocks = 1 + ((len + 8) / 64);
|
|
||||||
unsigned char* pend = pdata + 64 * blocks;
|
|
||||||
memset(pdata + len, 0, 64 * blocks - len);
|
|
||||||
pdata[len] = 0x80;
|
|
||||||
unsigned int bits = len * 8;
|
|
||||||
pend[-1] = (bits >> 0) & 0xff;
|
|
||||||
pend[-2] = (bits >> 8) & 0xff;
|
|
||||||
pend[-3] = (bits >> 16) & 0xff;
|
|
||||||
pend[-4] = (bits >> 24) & 0xff;
|
|
||||||
return blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned int pSHA256InitState[8] =
|
|
||||||
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
|
||||||
|
|
||||||
void SHA256Transform(void* pstate, void* pinput, const void* pinit)
|
|
||||||
{
|
|
||||||
SHA256_CTX ctx;
|
|
||||||
unsigned char data[64];
|
|
||||||
|
|
||||||
SHA256_Init(&ctx);
|
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
ctx.h[i] = ((uint32_t*)pinit)[i];
|
|
||||||
|
|
||||||
SHA256_Update(&ctx, data, sizeof(data));
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
((uint32_t*)pstate)[i] = ctx.h[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Unconfirmed transactions in the memory pool often depend on other
|
// Unconfirmed transactions in the memory pool often depend on other
|
||||||
// transactions in the memory pool. When we select transactions from the
|
// transactions in the memory pool. When we select transactions from the
|
||||||
@ -372,51 +335,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Pre-build hash buffers
|
|
||||||
//
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct unnamed2
|
|
||||||
{
|
|
||||||
int nVersion;
|
|
||||||
uint256 hashPrevBlock;
|
|
||||||
uint256 hashMerkleRoot;
|
|
||||||
unsigned int nTime;
|
|
||||||
unsigned int nBits;
|
|
||||||
unsigned int nNonce;
|
|
||||||
}
|
|
||||||
block;
|
|
||||||
unsigned char pchPadding0[64];
|
|
||||||
uint256 hash1;
|
|
||||||
unsigned char pchPadding1[64];
|
|
||||||
}
|
|
||||||
tmp;
|
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
|
||||||
|
|
||||||
tmp.block.nVersion = pblock->nVersion;
|
|
||||||
tmp.block.hashPrevBlock = pblock->hashPrevBlock;
|
|
||||||
tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
|
|
||||||
tmp.block.nTime = pblock->nTime;
|
|
||||||
tmp.block.nBits = pblock->nBits;
|
|
||||||
tmp.block.nNonce = pblock->nNonce;
|
|
||||||
|
|
||||||
FormatHashBlocks(&tmp.block, sizeof(tmp.block));
|
|
||||||
FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
|
|
||||||
|
|
||||||
// Byte swap all the input buffer
|
|
||||||
for (unsigned int i = 0; i < sizeof(tmp)/4; i++)
|
|
||||||
((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
|
|
||||||
|
|
||||||
// Precalc the first half of the first hash, which stays constant
|
|
||||||
SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
|
|
||||||
|
|
||||||
memcpy(pdata, &tmp.block, 128);
|
|
||||||
memcpy(phash1, &tmp.hash1, 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -427,34 +345,33 @@ int64_t nHPSTimerStart = 0;
|
|||||||
|
|
||||||
//
|
//
|
||||||
// ScanHash scans nonces looking for a hash with at least some zero bits.
|
// ScanHash scans nonces looking for a hash with at least some zero bits.
|
||||||
// It operates on big endian data. Caller does the byte reversing.
|
// The nonce is usually preserved between calls, but periodically or if the
|
||||||
// All input buffers are 16-byte aligned. nNonce is usually preserved
|
// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
|
||||||
// between calls, but periodically or if nNonce is 0xffff0000 or above,
|
// zero.
|
||||||
// the block is rebuilt and nNonce starts over at zero.
|
|
||||||
//
|
//
|
||||||
unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
|
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.
|
||||||
unsigned int& nNonce = *(unsigned int*)(pdata + 12);
|
CHash256 hasher;
|
||||||
for (;;)
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
{
|
ss << *pblock;
|
||||||
// Crypto++ SHA256
|
assert(ss.size() == 80);
|
||||||
// Hash pdata using pmidstate as the starting state into
|
hasher.Write((unsigned char*)&ss[0], 76);
|
||||||
// pre-formatted buffer phash1, then hash phash1 into phash
|
|
||||||
|
for (;;) {
|
||||||
nNonce++;
|
nNonce++;
|
||||||
SHA256Transform(phash1, pdata, pmidstate);
|
|
||||||
SHA256Transform(phash, phash1, pSHA256InitState);
|
// 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,
|
// Return the nonce if the hash has at least some zero bits,
|
||||||
// caller will check if it has enough to reach the target
|
// caller will check if it has enough to reach the target
|
||||||
if (((unsigned short*)phash)[14] == 0)
|
if (((uint16_t*)phash)[15] == 0)
|
||||||
return nNonce;
|
return true;
|
||||||
|
|
||||||
// If nothing found after trying for a while, return -1
|
// If nothing found after trying for a while, return -1
|
||||||
if ((nNonce & 0xffff) == 0)
|
if ((nNonce & 0xffff) == 0)
|
||||||
{
|
return false;
|
||||||
nHashesDone = 0xffff+1;
|
|
||||||
return (unsigned int) -1;
|
|
||||||
}
|
|
||||||
if ((nNonce & 0xfff) == 0)
|
if ((nNonce & 0xfff) == 0)
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
}
|
}
|
||||||
@ -541,46 +458,27 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||||||
LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
|
LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
|
||||||
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
|
::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
|
// Search
|
||||||
//
|
//
|
||||||
int64_t nStart = GetTime();
|
int64_t nStart = GetTime();
|
||||||
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
|
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
|
||||||
uint256 hashbuf[2];
|
uint256 hash;
|
||||||
uint256& hash = *alignup<16>(hashbuf);
|
uint32_t nNonce = 0;
|
||||||
|
uint32_t nOldNonce = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned int nHashesDone = 0;
|
bool fFound = ScanHash(pblock, nNonce, &hash);
|
||||||
unsigned int nNonceFound;
|
uint32_t nHashesDone = nNonce - nOldNonce;
|
||||||
|
nOldNonce = nNonce;
|
||||||
// Crypto++ SHA256
|
|
||||||
nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
|
|
||||||
(char*)&hash, nHashesDone);
|
|
||||||
|
|
||||||
// Check if something found
|
// Check if something found
|
||||||
if (nNonceFound != (unsigned int) -1)
|
if (fFound)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < sizeof(hash)/4; i++)
|
|
||||||
((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);
|
|
||||||
|
|
||||||
if (hash <= hashTarget)
|
if (hash <= hashTarget)
|
||||||
{
|
{
|
||||||
// Found a solution
|
// Found a solution
|
||||||
pblock->nNonce = ByteReverse(nNonceFound);
|
pblock->nNonce = nNonce;
|
||||||
assert(hash == pblock->GetHash());
|
assert(hash == pblock->GetHash());
|
||||||
|
|
||||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||||
@ -629,7 +527,7 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||||||
// Regtest mode doesn't require peers
|
// Regtest mode doesn't require peers
|
||||||
if (vNodes.empty() && Params().MiningRequiresPeers())
|
if (vNodes.empty() && Params().MiningRequiresPeers())
|
||||||
break;
|
break;
|
||||||
if (nBlockNonce >= 0xffff0000)
|
if (nNonce >= 0xffff0000)
|
||||||
break;
|
break;
|
||||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||||
break;
|
break;
|
||||||
@ -638,11 +536,9 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||||||
|
|
||||||
// Update nTime every few seconds
|
// Update nTime every few seconds
|
||||||
UpdateTime(*pblock, pindexPrev);
|
UpdateTime(*pblock, pindexPrev);
|
||||||
nBlockTime = ByteReverse(pblock->nTime);
|
|
||||||
if (Params().AllowMinDifficultyBlocks())
|
if (Params().AllowMinDifficultyBlocks())
|
||||||
{
|
{
|
||||||
// Changing pblock->nTime can change work required on testnet:
|
// Changing pblock->nTime can change work required on testnet:
|
||||||
nBlockBits = ByteReverse(pblock->nBits);
|
|
||||||
hashTarget.SetCompact(pblock->nBits);
|
hashTarget.SetCompact(pblock->nBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
|
|||||||
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
|
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
|
||||||
/** Modify the extranonce in a block */
|
/** Modify the extranonce in a block */
|
||||||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
|
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
|
||||||
/** Do mining precalculation */
|
|
||||||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
|
|
||||||
/** Check mined block */
|
/** Check mined block */
|
||||||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
|
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
|
||||||
/** Base sha256 mining transform */
|
|
||||||
void SHA256Transform(void* pstate, void* pinput, const void* pinit);
|
|
||||||
|
|
||||||
extern double dHashesPerSec;
|
extern double dHashesPerSec;
|
||||||
extern int64_t nHPSTimerStart;
|
extern int64_t nHPSTimerStart;
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
extern void SHA256Transform(void* pstate, void* pinput, const void* pinit);
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(miner_tests)
|
BOOST_AUTO_TEST_SUITE(miner_tests)
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -259,30 +257,4 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(sha256transform_equality)
|
|
||||||
{
|
|
||||||
unsigned int pSHA256InitState[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
|
||||||
|
|
||||||
|
|
||||||
// unsigned char pstate[32];
|
|
||||||
unsigned char pinput[64];
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
|
||||||
pinput[i] = i;
|
|
||||||
pinput[i+32] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 hash;
|
|
||||||
|
|
||||||
SHA256Transform(&hash, pinput, pSHA256InitState);
|
|
||||||
|
|
||||||
BOOST_TEST_MESSAGE(hash.GetHex());
|
|
||||||
|
|
||||||
uint256 hash_reference("0x2df5e1c65ef9f8cde240d23cae2ec036d31a15ec64bc68f64be242b1da6631f3");
|
|
||||||
|
|
||||||
BOOST_CHECK(hash == hash_reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
Loading…
Reference in New Issue
Block a user