X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=9f12829042b84286cc09f09f29679412a3bd03a8;hb=4664aae3fe2eba4eec84d20f1e7e701ceeeb49bd;hp=731402194df7f89da6790c95b1c87961760474d5;hpb=926e14b362cd830cdca96dd37a9ebad247399420;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index 7314021..9f12829 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,9 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" +#include "checkpoints.h" #include "db.h" #include "net.h" #include "init.h" @@ -21,17 +23,15 @@ set setpwalletRegistered; CCriticalSection cs_main; -CCriticalSection cs_mapPubKeys; -map > mapPubKeys; - -map mapTransactions; +static map mapTransactions; CCriticalSection cs_mapTransactions; unsigned int nTransactionsUpdated = 0; map mapNextTx; map mapBlockIndex; uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); -CBigNum bnProofOfWorkLimit(~uint256(0) >> 32); +static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32); +const int nInitialBlockThreshold = 120; // Regard blocks up until N-threshold as "initial download" CBlockIndex* pindexGenesisBlock = NULL; int nBestHeight = -1; CBigNum bnBestChainWork = 0; @@ -53,7 +53,6 @@ int64 nHPSTimerStart; // Settings int fGenerateBitcoins = false; int64 nTransactionFee = 0; -CAddress addrIncoming; int fLimitProcessors = false; int nLimitProcessors = 1; int fMinimizeToTray = true; @@ -296,9 +295,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) bool CTransaction::CheckTransaction() const { // Basic checks that don't depend on any context - if (vin.empty() || vout.empty()) - return error("CTransaction::CheckTransaction() : vin or vout empty"); - + if (vin.empty()) + return error("CTransaction::CheckTransaction() : vin empty"); + if (vout.empty()) + return error("CTransaction::CheckTransaction() : vout empty"); // Size limits if (::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE) return error("CTransaction::CheckTransaction() : size limits failed"); @@ -316,6 +316,15 @@ bool CTransaction::CheckTransaction() const return error("CTransaction::CheckTransaction() : txout total out of range"); } + // Check for duplicate inputs + set vInOutPoints; + BOOST_FOREACH(const CTxIn& txin, vin) + { + if (vInOutPoints.count(txin.prevout)) + return false; + vInOutPoints.insert(txin.prevout); + } + if (IsCoinBase()) { if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100) @@ -402,10 +411,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Check against previous transactions map mapUnused; int64 nFees = 0; - if (!ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), pindexBest, nFees, false, false)) + bool fInvalid = false; + if (!ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), pindexBest, nFees, false, false, 0, fInvalid)) { - if (pfMissingInputs) - *pfMissingInputs = true; + if (fInvalid) + return error("AcceptToMemoryPool() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str()); return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); } @@ -642,19 +652,65 @@ int64 static GetBlockValue(int nHeight, int64 nFees) return nSubsidy + nFees; } -unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast) +static const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks +static const int64 nTargetSpacing = 10 * 60; +static const int64 nInterval = nTargetTimespan / nTargetSpacing; + +// +// minimum amount of work that could possibly be required nTime after +// minimum work required was nBase +// +unsigned int ComputeMinWork(unsigned int nBase, int64 nTime) +{ + // Testnet has min-difficulty blocks + // after nTargetSpacing*2 time between blocks: + if (fTestNet && nTime > nTargetSpacing*2) + return bnProofOfWorkLimit.GetCompact(); + + CBigNum bnResult; + bnResult.SetCompact(nBase); + while (nTime > 0 && bnResult < bnProofOfWorkLimit) + { + // Maximum 400% adjustment... + bnResult *= 4; + // ... in best-case exactly 4-times-normal target time + nTime -= nTargetTimespan*4; + } + if (bnResult > bnProofOfWorkLimit) + bnResult = bnProofOfWorkLimit; + return bnResult.GetCompact(); +} + +unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlock *pblock) { - const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks - const int64 nTargetSpacing = 10 * 60; - const int64 nInterval = nTargetTimespan / nTargetSpacing; + unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact(); // Genesis block if (pindexLast == NULL) - return bnProofOfWorkLimit.GetCompact(); + return nProofOfWorkLimit; // Only change once per interval if ((pindexLast->nHeight+1) % nInterval != 0) + { + // Special rules for testnet after 15 Feb 2012: + if (fTestNet && pblock->nTime > 1329264000) + { + // If the new block's timestamp is more than 2* 10 minutes + // then allow mining of a min-difficulty block. + if (pblock->nTime - pindexLast->nTime > nTargetSpacing*2) + return nProofOfWorkLimit; + else + { + // Return the last non-special-min-difficulty-rules-block + const CBlockIndex* pindex = pindexLast; + while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit) + pindex = pindex->pprev; + return pindex->nBits; + } + } + return pindexLast->nBits; + } // Go back by what we want to be 14 days worth of blocks const CBlockIndex* pindexFirst = pindexLast; @@ -706,7 +762,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) bool IsInitialBlockDownload() { - if (pindexBest == NULL || (!fTestNet && nBestHeight < 118000)) + if (pindexBest == NULL || nBestHeight < (Checkpoints::GetTotalBlocksEstimate()-nInitialBlockThreshold)) return true; static int64 nLastUpdate; static CBlockIndex* pindexLastBest; @@ -778,8 +834,15 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb) bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPool, CDiskTxPos posThisTx, - CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee) + CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee, + bool& fInvalid) { + // FetchInputs can return false either because we just haven't seen some inputs + // (in which case the transaction should be stored as an orphan) + // or because the transaction is malformed (in which case the transaction should + // be dropped). If tx is definitely invalid, fInvalid will be set to true. + fInvalid = false; + // Take over previous transactions' spent pointers if (!IsCoinBase()) { @@ -791,7 +854,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPoo // Read txindex CTxIndex txindex; bool fFound = true; - if (fMiner && mapTestPool.count(prevout.hash)) + if ((fBlock || fMiner) && mapTestPool.count(prevout.hash)) { // Get txindex from current proposed changes txindex = mapTestPool[prevout.hash]; @@ -826,7 +889,12 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPoo } if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) + { + // Revisit this if/when transaction replacement is implemented and allows + // adding inputs: + fInvalid = true; return error("ConnectInputs() : %s prevout.n out of range %d %d %d prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()); + } // If prev is coinbase, check that it's matured if (txPrev.IsCoinBase()) @@ -851,12 +919,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPoo txindex.vSpent[prevout.n] = posThisTx; // Write back - if (fBlock) - { - if (!txdb.UpdateTxIndex(prevout.hash, txindex)) - return error("ConnectInputs() : UpdateTxIndex failed"); - } - else if (fMiner) + if (fBlock || fMiner) { mapTestPool[prevout.hash] = txindex; } @@ -878,9 +941,8 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPoo if (fBlock) { - // Add transaction to disk index - if (!txdb.AddTxIndex(*this, posThisTx, pindexBlock->nHeight)) - return error("ConnectInputs() : AddTxPos failed"); + // Add transaction to changes + mapTestPool[GetHash()] = CTxIndex(posThisTx, vout.size()); } else if (fMiner) { @@ -969,16 +1031,23 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) //// issue here: it doesn't know the version unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK) - 1 + GetSizeOfCompactSize(vtx.size()); - map mapUnused; + map mapQueuedChanges; int64 nFees = 0; BOOST_FOREACH(CTransaction& tx, vtx) { CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos); nTxPos += ::GetSerializeSize(tx, SER_DISK); - if (!tx.ConnectInputs(txdb, mapUnused, posThisTx, pindex, nFees, true, false)) + bool fInvalid; + if (!tx.ConnectInputs(txdb, mapQueuedChanges, posThisTx, pindex, nFees, true, false, 0, fInvalid)) return false; } + // Write queued txindex changes + for (map::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi) + { + if (!txdb.UpdateTxIndex((*mi).first, (*mi).second)) + return error("ConnectBlock() : UpdateTxIndex failed"); + } if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees)) return false; @@ -1259,7 +1328,7 @@ bool CBlock::AcceptBlock() int nHeight = pindexPrev->nHeight+1; // Check proof of work - if (nBits != GetNextWorkRequired(pindexPrev)) + if (nBits != GetNextWorkRequired(pindexPrev, this)) return error("AcceptBlock() : incorrect proof of work"); // Check timestamp against prev @@ -1272,15 +1341,8 @@ bool CBlock::AcceptBlock() return error("AcceptBlock() : contains a non-final transaction"); // Check that the block chain matches the known block chain up to a checkpoint - if (!fTestNet) - if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) || - (nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) || - (nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) || - (nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) || - (nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")) || - (nHeight == 105000 && hash != uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")) || - (nHeight == 118000 && hash != uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553"))) - return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight); + if (!Checkpoints::CheckBlock(nHeight, hash)) + return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight); // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK))) @@ -1296,7 +1358,7 @@ bool CBlock::AcceptBlock() if (hashBestChain == hash) CRITICAL_BLOCK(cs_vNodes) BOOST_FOREACH(CNode* pnode, vNodes) - if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 118000)) + if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 140700)) pnode->PushInventory(CInv(MSG_BLOCK, hash)); return true; @@ -1315,6 +1377,26 @@ bool static ProcessBlock(CNode* pfrom, CBlock* pblock) if (!pblock->CheckBlock()) return error("ProcessBlock() : CheckBlock FAILED"); + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + if (pcheckpoint && pblock->hashPrevBlock != hashBestChain) + { + // Extra checks to prevent "fill up memory by spamming with bogus blocks" + int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime; + if (deltaTime < 0) + { + return error("ProcessBlock() : block with timestamp before last checkpoint"); + } + CBigNum bnNewBlock; + bnNewBlock.SetCompact(pblock->nBits); + CBigNum bnRequired; + bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); + if (bnNewBlock > bnRequired) + { + return error("ProcessBlock() : block with too little proof-of-work"); + } + } + + // If don't already have its previous block, shunt it off to holding area until we get it if (!mapBlockIndex.count(pblock->hashPrevBlock)) { @@ -1363,47 +1445,6 @@ bool static ProcessBlock(CNode* pfrom, CBlock* pblock) -template -bool static ScanMessageStart(Stream& s) -{ - // Scan ahead to the next pchMessageStart, which should normally be immediately - // at the file pointer. Leaves file pointer at end of pchMessageStart. - s.clear(0); - short prevmask = s.exceptions(0); - const char* p = BEGIN(pchMessageStart); - try - { - loop - { - char c; - s.read(&c, 1); - if (s.fail()) - { - s.clear(0); - s.exceptions(prevmask); - return false; - } - if (*p != c) - p = BEGIN(pchMessageStart); - if (*p == c) - { - if (++p == END(pchMessageStart)) - { - s.clear(0); - s.exceptions(prevmask); - return true; - } - } - } - } - catch (...) - { - s.clear(0); - s.exceptions(prevmask); - return false; - } -} - bool CheckDiskSpace(uint64 nAdditionalBytes) { uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available; @@ -1673,7 +1714,7 @@ string GetWarnings(string strFor) return strStatusBar; else if (strFor == "rpc") return strRPC; - assert(("GetWarnings() : invalid parameter", false)); + assert(!"GetWarnings() : invalid parameter"); return "error"; } @@ -1754,16 +1795,17 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv) // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ascii, not valid as UTF-8, and produce // a large 4-byte int at any alignment. -char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 }; +unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 }; bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { static map > mapReuseKey; RandAddSeedPerfmon(); - if (fDebug) + if (fDebug) { printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); - printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size()); + printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size()); + } if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { printf("dropmessagestest DROPPING RECV MESSAGE\n"); @@ -1840,7 +1882,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // Ask the first connected node for block updates static int nAskedForBlocks; - if (!pfrom->fClient && (nAskedForBlocks < 1 || vNodes.size() <= 1)) + if (!pfrom->fClient && + (pfrom->nVersion < 32000 || pfrom->nVersion >= 32400) && + (nAskedForBlocks < 1 || vNodes.size() <= 1)) { nAskedForBlocks++; pfrom->PushGetBlocks(pindexBest, uint256(0)); @@ -1884,6 +1928,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return error("message addr size() = %d", vAddr.size()); // Store the new addresses + CAddrDB addrDB; + addrDB.TxnBegin(); int64 nNow = GetAdjustedTime(); int64 nSince = nNow - 10 * 60; BOOST_FOREACH(CAddress& addr, vAddr) @@ -1895,7 +1941,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) continue; if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) addr.nTime = nNow - 5 * 24 * 60 * 60; - AddAddress(addr, 2 * 60 * 60); + AddAddress(addr, 2 * 60 * 60, &addrDB); pfrom->AddAddressKnown(addr); if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) { @@ -1926,6 +1972,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } } } + addrDB.TxnCommit(); // Save addresses (it's ok if this fails) if (vAddr.size() < 1000) pfrom->fGetAddr = false; } @@ -1946,7 +1993,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->AddInventoryKnown(inv); bool fAlreadyHave = AlreadyHave(txdb, inv); - printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new"); + if (fDebug) + printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new"); if (!fAlreadyHave) pfrom->AskFor(inv); @@ -2025,20 +2073,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pindex) pindex = pindex->pnext; int nLimit = 500 + locator.GetDistanceBack(); + unsigned int nBytes = 0; printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit); for (; pindex; pindex = pindex->pnext) { if (pindex->GetBlockHash() == hashStop) { - printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str()); + printf(" getblocks stopping at %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes); break; } pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); - if (--nLimit <= 0) + CBlock block; + block.ReadFromDisk(pindex, true); + nBytes += block.GetSerializeSize(SER_NETWORK); + if (--nLimit <= 0 || nBytes >= SendBufferSize()/2) { // When this block is requested, we'll send an inv that'll make them // getblocks the next batch of inventory. - printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str()); + printf(" getblocks stopping at limit %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes); pfrom->hashContinue = pindex->GetBlockHash(); break; } @@ -2193,7 +2245,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // Keep giving the same key to the same ip until they use it if (!mapReuseKey.count(pfrom->addr.ip)) - mapReuseKey[pfrom->addr.ip] = pwalletMain->GetKeyFromKeyPool(); + pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr.ip], true); // Send back approval of order and pubkey to use CScript scriptPubKey; @@ -2548,6 +2600,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) vGetData.clear(); } } + mapAlreadyAskedFor[inv] = nNow; pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) @@ -2634,7 +2687,7 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1 } } - +// Some explaining would be appreciated class COrphan { public: @@ -2762,12 +2815,13 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Transaction fee required depends on block size bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority)); - int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree, true); + int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree); // Connecting shouldn't fail due to dependency on other memory pool transactions // because we're already processing them in order of dependency map mapTestPoolTmp(mapTestPool); - if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee)) + bool fInvalid; + if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee, fInvalid)) continue; swap(mapTestPool, mapTestPoolTmp); @@ -2798,23 +2852,24 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); - pblock->nBits = GetNextWorkRequired(pindexPrev); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock.get()); pblock->nNonce = 0; return pblock.release(); } -void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime) +void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce) { // Update nExtraNonce - int64 nNow = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); - if (++nExtraNonce >= 0x7f && nNow > nPrevTime+1) + static uint256 hashPrevBlock; + if (hashPrevBlock != pblock->hashPrevBlock) { - nExtraNonce = 1; - nPrevTime = nNow; + nExtraNonce = 0; + hashPrevBlock = pblock->hashPrevBlock; } - pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce); + ++nExtraNonce; + pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nTime << CBigNum(nExtraNonce); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } @@ -2890,7 +2945,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) reservekey.KeepKey(); // Track how many getdata requests this block gets - CRITICAL_BLOCK(wallet.cs_mapRequestCount) + CRITICAL_BLOCK(wallet.cs_wallet) wallet.mapRequestCount[pblock->GetHash()] = 0; // Process this block the same as if we had received it from another node @@ -2912,7 +2967,6 @@ void static BitcoinMiner(CWallet *pwallet) // Each thread has its own key and counter CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; - int64 nPrevTime = 0; while (fGenerateBitcoins) { @@ -2939,7 +2993,7 @@ void static BitcoinMiner(CWallet *pwallet) auto_ptr pblock(CreateNewBlock(reservekey)); if (!pblock.get()) return; - IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce, nPrevTime); + IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce); printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());