aboutsummaryrefslogtreecommitdiff
path: root/src/miner.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-06-21 22:43:02 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2014-06-21 22:52:46 +0200
commit8f59251b83cd9c862aee53dd50ce32bcab12ed6d (patch)
tree0cc4942365bf1595a02c7da6f7156a0552bc6f74 /src/miner.cpp
parentb4ccf0a5c78fd5479d5b2bbf289b6f6c5d8a70a3 (diff)
parenta0495bb68c6eff9c732d458bacab10490d6452b4 (diff)
downloadbitcoin-8f59251b83cd9c862aee53dd50ce32bcab12ed6d.tar.xz
Merge pull request #4100
a0495bb Add <Hasher>::OUTPUT_SIZE (Pieter Wuille) 4791b99 crypto: create a separate lib for crypto functions (Cory Fields) f2647cc crypto: explicitly check for byte read/write functions (Cory Fields) 5437248 build: move bitcoin-config.h to its own directory (Cory Fields) 3820e01 Extend and move all crypto tests to crypto_tests.cpp (Pieter Wuille) 7ecd973 Move {Read,Write}{LE,BE}{32,64} to common.h and use builtins if possible (Pieter Wuille) a5bc9c0 Add built-in RIPEMD-160 implementation (Pieter Wuille) 13b5dfe Move crypto implementations to src/crypto/ (Pieter Wuille) 1cc344c Add built-in SHA-1 implementation. (Pieter Wuille) 85aab2a Switch miner.cpp to use sha2 instead of OpenSSL. (Pieter Wuille) cf0c47b Remove getwork() RPC call (Pieter Wuille) 7b4737c Switch script.cpp and hash.cpp to use sha2.cpp instead of OpenSSL. (Pieter Wuille) 977cdad Add a built-in SHA256/SHA512 implementation. (Pieter Wuille)
Diffstat (limited to 'src/miner.cpp')
-rw-r--r--src/miner.cpp161
1 files changed, 30 insertions, 131 deletions
diff --git a/src/miner.cpp b/src/miner.cpp
index 87779efbbd..7efca7cfff 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -6,6 +6,7 @@
#include "miner.h"
#include "core.h"
+#include "hash.h"
#include "main.h"
#include "net.h"
#ifdef ENABLE_WALLET
@@ -13,47 +14,12 @@
#endif
using namespace std;
+
//////////////////////////////////////////////////////////////////////////////
//
// 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
// transactions in the memory pool. When we select transactions from the
@@ -369,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
//////////////////////////////////////////////////////////////////////////////
//
@@ -424,34 +345,33 @@ int64_t nHPSTimerStart = 0;
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
-// It operates on big endian data. Caller does the byte reversing.
-// All input buffers are 16-byte aligned. nNonce is usually preserved
-// between calls, but periodically or if nNonce is 0xffff0000 or above,
-// the block is rebuilt and nNonce starts over at zero.
+// 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.
//
-unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
-{
- unsigned int& nNonce = *(unsigned int*)(pdata + 12);
- for (;;)
- {
- // Crypto++ SHA256
- // Hash pdata using pmidstate as the starting state into
- // pre-formatted buffer phash1, then hash phash1 into phash
+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);
+
+ for (;;) {
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,
// caller will check if it has enough to reach the target
- if (((unsigned short*)phash)[14] == 0)
- return nNonce;
+ if (((uint16_t*)phash)[15] == 0)
+ return true;
// If nothing found after trying for a while, return -1
if ((nNonce & 0xffff) == 0)
- {
- nHashesDone = 0xffff+1;
- return (unsigned int) -1;
- }
+ return false;
if ((nNonce & 0xfff) == 0)
boost::this_thread::interruption_point();
}
@@ -539,45 +459,26 @@ void static BitcoinMiner(CWallet *pwallet)
::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_t nStart = GetTime();
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
- uint256 hashbuf[2];
- uint256& hash = *alignup<16>(hashbuf);
+ uint256 hash;
+ uint32_t nNonce = 0;
+ uint32_t nOldNonce = 0;
while (true)
{
- unsigned int nHashesDone = 0;
- unsigned int nNonceFound;
-
- // Crypto++ SHA256
- nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
- (char*)&hash, nHashesDone);
+ bool fFound = ScanHash(pblock, nNonce, &hash);
+ uint32_t nHashesDone = nNonce - nOldNonce;
+ nOldNonce = nNonce;
// 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)
{
// Found a solution
- pblock->nNonce = ByteReverse(nNonceFound);
+ pblock->nNonce = nNonce;
assert(hash == pblock->GetHash());
SetThreadPriority(THREAD_PRIORITY_NORMAL);
@@ -626,7 +527,7 @@ void static BitcoinMiner(CWallet *pwallet)
// Regtest mode doesn't require peers
if (vNodes.empty() && Params().MiningRequiresPeers())
break;
- if (nBlockNonce >= 0xffff0000)
+ if (nNonce >= 0xffff0000)
break;
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
break;
@@ -635,11 +536,9 @@ void static BitcoinMiner(CWallet *pwallet)
// Update nTime every few seconds
UpdateTime(*pblock, pindexPrev);
- nBlockTime = ByteReverse(pblock->nTime);
if (Params().AllowMinDifficultyBlocks())
{
// Changing pblock->nTime can change work required on testnet:
- nBlockBits = ByteReverse(pblock->nBits);
hashTarget.SetCompact(pblock->nBits);
}
}