aboutsummaryrefslogtreecommitdiff
path: root/src/miner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/miner.cpp')
-rw-r--r--src/miner.cpp183
1 files changed, 43 insertions, 140 deletions
diff --git a/src/miner.cpp b/src/miner.cpp
index 87779efbbd..63ce125067 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
@@ -120,14 +86,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
// Create coinbase tx
- CTransaction txNew;
+ CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
- // Add our coinbase tx as first transaction
- pblock->vtx.push_back(txNew);
+ // Add dummy coinbase tx as first transaction
+ pblock->vtx.push_back(CTransaction());
pblocktemplate->vTxFees.push_back(-1); // updated at end
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
@@ -288,8 +254,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
continue;
CTxUndo txundo;
- uint256 hash = tx.GetHash();
- UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
+ const uint256& hash = tx.GetHash();
+ UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
// Added
pblock->vtx.push_back(tx);
@@ -328,7 +294,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
nLastBlockSize = nBlockSize;
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
- pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
+ // Compute final coinbase transaction.
+ txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
+ txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
+ pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
// Fill in header
@@ -336,7 +305,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(*pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
- pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CBlockIndex indexDummy(*pblock);
@@ -362,58 +330,15 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
- pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
- assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
+ CMutableTransaction txCoinbase(pblock->vtx[0]);
+ txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
+ assert(txCoinbase.vin[0].scriptSig.size() <= 100);
+ pblock->vtx[0] = txCoinbase;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}
-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 +349,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 +463,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 +531,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 +540,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);
}
}