X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=53cdab175a595c5287874cb21744fffe13f27a07;hb=4e87d341f75f13bbd7d108c31c03886fbc4df56f;hp=8949b97be659fedc3a40b48d14551252589f8d06;hpb=e89b9f6a2abaa120ff0fc3cea9ae364e8cbd25e4;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index 8949b97..53cdab1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "net.h" #include "init.h" #include "cryptopp/sha.h" +#include #include using namespace std; @@ -15,8 +16,14 @@ using namespace boost; // Global state // +CCriticalSection cs_setpwalletRegistered; +set setpwalletRegistered; + CCriticalSection cs_main; +CCriticalSection cs_mapPubKeys; +map > mapPubKeys; + map mapTransactions; CCriticalSection cs_mapTransactions; unsigned int nTransactionsUpdated = 0; @@ -25,6 +32,8 @@ map mapNextTx; map mapBlockIndex; uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); CBigNum bnProofOfWorkLimit(~uint256(0) >> 32); +const int nTotalBlocksEstimate = 134444; // Conservative estimate of total nr of blocks on main chain +const int nInitialBlockThreshold = 120; // Regard blocks up until N-threshold as "initial download" CBlockIndex* pindexGenesisBlock = NULL; int nBestHeight = -1; CBigNum bnBestChainWork = 0; @@ -39,25 +48,6 @@ multimap mapOrphanBlocksByPrev; map mapOrphanTransactions; multimap mapOrphanTransactionsByPrev; -map mapWallet; -vector vWalletUpdated; -CCriticalSection cs_mapWallet; - -map, CPrivKey> mapKeys; -map > mapPubKeys; -CCriticalSection cs_mapKeys; -CKey keyUser; - -map mapRequestCount; -CCriticalSection cs_mapRequestCount; - -map mapAddressBook; -CCriticalSection cs_mapAddressBook; - -set setKeyPool; -CCriticalSection cs_setKeyPool; - -vector vchDefaultKey; double dHashesPerSec; int64 nHPSTimerStart; @@ -84,10 +74,95 @@ int fUseUPnP = false; ////////////////////////////////////////////////////////////////////////////// // +// dispatching functions +// + +void RegisterWallet(CWallet* pwalletIn) +{ + CRITICAL_BLOCK(cs_setpwalletRegistered) + { + setpwalletRegistered.insert(pwalletIn); + } +} + +void UnregisterWallet(CWallet* pwalletIn) +{ + CRITICAL_BLOCK(cs_setpwalletRegistered) + { + setpwalletRegistered.erase(pwalletIn); + } +} + +bool static IsFromMe(CTransaction& tx) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + if (pwallet->IsFromMe(tx)) + return true; + return false; +} + +bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + if (pwallet->GetTransaction(hashTx,wtx)) + return true; + return false; +} + +void static EraseFromWallets(uint256 hash) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->EraseFromWallet(hash); +} + +void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); +} + +void static SetBestChain(const CBlockLocator& loc) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->SetBestChain(loc); +} + +void static UpdatedTransaction(const uint256& hashTx) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->UpdatedTransaction(hashTx); +} + +void static PrintWallets(const CBlock& block) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->PrintWallet(block); +} + +void static Inventory(const uint256& hash) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->Inventory(hash); +} + +void static ResendWalletTransactions() +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->ResendWalletTransactions(); +} + + + + + + + +////////////////////////////////////////////////////////////////////////////// +// // mapOrphanTransactions // -void AddOrphanTx(const CDataStream& vMsg) +void static AddOrphanTx(const CDataStream& vMsg) { CTransaction tx; CDataStream(vMsg) >> tx; @@ -99,7 +174,7 @@ void AddOrphanTx(const CDataStream& vMsg) mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg)); } -void EraseOrphanTx(uint256 hash) +void static EraseOrphanTx(uint256 hash) { if (!mapOrphanTransactions.count(hash)) return; @@ -357,7 +432,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi nLastTime = nNow; // -limitfreerelay unit is thousand-bytes-per-minute // At default rate it would take over a month to fill 1GB - if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe()) + if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this)) return error("AcceptToMemoryPool() : free transaction rejected by rate limiter"); if (fDebug) printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); @@ -380,7 +455,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi ///// are we sure this is ok when loading transactions or restoring block txes // If updated, erase old tx from wallet if (ptxOld) - EraseFromWallet(ptxOld->GetHash()); + EraseFromWallets(ptxOld->GetHash()); printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str()); return true; @@ -551,8 +626,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) return true; } - -uint256 GetOrphanRoot(const CBlock* pblock) +uint256 static GetOrphanRoot(const CBlock* pblock) { // Work back to the first block in the orphan chain while (mapOrphanBlocks.count(pblock->hashPrevBlock)) @@ -560,7 +634,7 @@ uint256 GetOrphanRoot(const CBlock* pblock) return pblock->GetHash(); } -int64 GetBlockValue(int nHeight, int64 nFees) +int64 static GetBlockValue(int nHeight, int64 nFees) { int64 nSubsidy = 50 * COIN; @@ -570,7 +644,7 @@ int64 GetBlockValue(int nHeight, int64 nFees) return nSubsidy + nFees; } -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast) +unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast) { const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks const int64 nTargetSpacing = 10 * 60; @@ -632,9 +706,22 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) return true; } +// Return conservative estimate of total number of blocks, 0 if unknown +int GetTotalBlocksEstimate() +{ + if(fTestNet) + { + return 0; + } + else + { + return nTotalBlocksEstimate; + } +} + bool IsInitialBlockDownload() { - if (pindexBest == NULL || (!fTestNet && nBestHeight < 118000)) + if (pindexBest == NULL || nBestHeight < (GetTotalBlocksEstimate()-nInitialBlockThreshold)) return true; static int64 nLastUpdate; static CBlockIndex* pindexLastBest; @@ -647,7 +734,7 @@ bool IsInitialBlockDownload() pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60); } -void InvalidChainFound(CBlockIndex* pindexNew) +void static InvalidChainFound(CBlockIndex* pindexNew) { if (pindexNew->bnChainWork > bnBestInvalidWork) { @@ -923,12 +1010,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) // Watch for transactions paying to me BOOST_FOREACH(CTransaction& tx, vtx) - AddToWalletIfInvolvingMe(tx, this, true); + SyncWithWallets(tx, this, true); return true; } -bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) +bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) { printf("REORGANIZE\n"); @@ -1066,10 +1153,8 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // Update best block in wallet (so we can detect restored wallets) if (!IsInitialBlockDownload()) { - CWalletDB walletdb; const CBlockLocator locator(pindexNew); - if (!walletdb.WriteBestBlock(locator)) - return error("SetBestChain() : WriteWalletBest failed"); + ::SetBestChain(locator); } // New best block @@ -1123,8 +1208,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) { // Notify UI to display prev block's coinbase if it was ours static uint256 hashPrevBestCoinBase; - CRITICAL_BLOCK(cs_mapWallet) - vWalletUpdated.push_back(hashPrevBestCoinBase); + UpdatedTransaction(hashPrevBestCoinBase); hashPrevBestCoinBase = vtx[0].GetHash(); } @@ -1210,7 +1294,8 @@ bool CBlock::AcceptBlock() (nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) || (nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")) || (nHeight == 105000 && hash != uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")) || - (nHeight == 118000 && hash != uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553"))) + (nHeight == 118000 && hash != uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553")) || + (nHeight == 134444 && hash != uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))) return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight); // Write block to history file @@ -1227,13 +1312,13 @@ 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 : 134444)) pnode->PushInventory(CInv(MSG_BLOCK, hash)); return true; } -bool ProcessBlock(CNode* pfrom, CBlock* pblock) +bool static ProcessBlock(CNode* pfrom, CBlock* pblock) { // Check for duplicate uint256 hash = pblock->GetHash(); @@ -1295,7 +1380,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) template -bool ScanMessageStart(Stream& s) +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. @@ -1510,7 +1595,7 @@ void PrintBlockTree() for (int i = 0; i < nCol; i++) printf("| "); printf("|\n"); - } + } nPrevCol = nCol; // print columns @@ -1528,16 +1613,7 @@ void PrintBlockTree() DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(), block.vtx.size()); - CRITICAL_BLOCK(cs_mapWallet) - { - if (mapWallet.count(block.vtx[0].GetHash())) - { - CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; - printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); - } - } - printf("\n"); - + PrintWallets(block); // put the main timechain first vector& vNext = mapNext[pindex]; @@ -1677,7 +1753,7 @@ bool CAlert::ProcessAlert() // -bool AlreadyHave(CTxDB& txdb, const CInv& inv) +bool static AlreadyHave(CTxDB& txdb, const CInv& inv) { switch (inv.type) { @@ -1697,7 +1773,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv) char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 }; -bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) +bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { static map > mapReuseKey; RandAddSeedPerfmon(); @@ -1894,12 +1970,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); // Track requests for our stuff - CRITICAL_BLOCK(cs_mapRequestCount) - { - map::iterator mi = mapRequestCount.find(inv.hash); - if (mi != mapRequestCount.end()) - (*mi).second++; - } + Inventory(inv.hash); } } @@ -1952,12 +2023,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } // Track requests for our stuff - CRITICAL_BLOCK(cs_mapRequestCount) - { - map::iterator mi = mapRequestCount.find(inv.hash); - if (mi != mapRequestCount.end()) - (*mi).second++; - } + Inventory(inv.hash); } } @@ -1975,20 +2041,24 @@ bool 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; } @@ -2045,7 +2115,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) bool fMissingInputs = false; if (tx.AcceptToMemoryPool(true, &fMissingInputs)) { - AddToWalletIfInvolvingMe(tx, NULL, true); + SyncWithWallets(tx, NULL, true); RelayMessage(inv, vMsg); mapAlreadyAskedFor.erase(inv); vWorkQueue.push_back(inv.hash); @@ -2066,7 +2136,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (tx.AcceptToMemoryPool(true)) { printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str()); - AddToWalletIfInvolvingMe(tx, NULL, true); + SyncWithWallets(tx, NULL, true); RelayMessage(inv, vMsg); mapAlreadyAskedFor.erase(inv); vWorkQueue.push_back(inv.hash); @@ -2143,7 +2213,7 @@ bool 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] = GetKeyFromKeyPool(); + mapReuseKey[pfrom->addr.ip] = pwalletMain->GetOrReuseKeyFromPool(); // Send back approval of order and pubkey to use CScript scriptPubKey; @@ -2152,37 +2222,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } - else if (strCommand == "submitorder") - { - uint256 hashReply; - vRecv >> hashReply; - - if (!GetBoolArg("-allowreceivebyip")) - { - pfrom->PushMessage("reply", hashReply, (int)2); - return true; - } - - CWalletTx wtxNew; - vRecv >> wtxNew; - wtxNew.fFromMe = false; - - // Broadcast - if (!wtxNew.AcceptWalletTransaction()) - { - pfrom->PushMessage("reply", hashReply, (int)1); - return error("submitorder AcceptWalletTransaction() failed, returning error 1"); - } - wtxNew.fTimeReceivedIsTxTime = true; - AddToWallet(wtxNew); - wtxNew.RelayWalletTransaction(); - mapReuseKey.erase(pfrom->addr.ip); - - // Send back confirmation - pfrom->PushMessage("reply", hashReply, (int)0); - } - - else if (strCommand == "reply") { uint256 hashReply; @@ -2239,7 +2278,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return true; } - bool ProcessMessages(CNode* pfrom) { CDataStream& vRecv = pfrom->vRecv; @@ -2359,8 +2397,6 @@ bool ProcessMessages(CNode* pfrom) } - - bool SendMessages(CNode* pto, bool fSendTrickle) { CRITICAL_BLOCK(cs_main) @@ -2483,16 +2519,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // always trickle our own transactions if (!fTrickleWait) { - TRY_CRITICAL_BLOCK(cs_mapWallet) - { - map::iterator mi = mapWallet.find(inv.hash); - if (mi != mapWallet.end()) - { - CWalletTx& wtx = (*mi).second; - if (wtx.fFromMe) - fTrickleWait = true; - } - } + CWalletTx wtx; + if (GetTransaction(inv.hash, wtx)) + if (wtx.fFromMe) + fTrickleWait = true; } if (fTrickleWait) @@ -2565,7 +2595,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // BitcoinMiner // -int FormatHashBlocks(void* pbuffer, unsigned int len) +int static FormatHashBlocks(void* pbuffer, unsigned int len) { unsigned char* pdata = (unsigned char*)pbuffer; unsigned int blocks = 1 + ((len + 8) / 64); @@ -2598,7 +2628,7 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit) // between calls, but periodically or if nNonce is 0xffff0000 or above, // the block is rebuilt and nNonce starts over at zero. // -unsigned int ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone) +unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone) { unsigned int& nNonce = *(unsigned int*)(pdata + 12); for (;;) @@ -2855,7 +2885,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash } -bool CheckWork(CBlock* pblock, CReserveKey& reservekey) +bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) { uint256 hash = pblock->GetHash(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); @@ -2880,8 +2910,8 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey) reservekey.KeepKey(); // Track how many getdata requests this block gets - CRITICAL_BLOCK(cs_mapRequestCount) - mapRequestCount[pblock->GetHash()] = 0; + CRITICAL_BLOCK(wallet.cs_mapRequestCount) + wallet.mapRequestCount[pblock->GetHash()] = 0; // Process this block the same as if we had received it from another node if (!ProcessBlock(NULL, pblock)) @@ -2892,13 +2922,15 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey) return true; } -void BitcoinMiner() +void static ThreadBitcoinMiner(void* parg); + +void static BitcoinMiner(CWallet *pwallet) { printf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); // Each thread has its own key and counter - CReserveKey reservekey; + CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; int64 nPrevTime = 0; @@ -2974,7 +3006,7 @@ void BitcoinMiner() assert(hash == pblock->GetHash()); SetThreadPriority(THREAD_PRIORITY_NORMAL); - CheckWork(pblock.get(), reservekey); + CheckWork(pblock.get(), *pwalletMain, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); break; } @@ -3035,12 +3067,13 @@ void BitcoinMiner() } } -void ThreadBitcoinMiner(void* parg) +void static ThreadBitcoinMiner(void* parg) { + CWallet* pwallet = (CWallet*)parg; try { vnThreadsRunning[3]++; - BitcoinMiner(); + BitcoinMiner(pwallet); vnThreadsRunning[3]--; } catch (std::exception& e) { @@ -3058,12 +3091,12 @@ void ThreadBitcoinMiner(void* parg) } -void GenerateBitcoins(bool fGenerate) +void GenerateBitcoins(bool fGenerate, CWallet* pwallet) { if (fGenerateBitcoins != fGenerate) { fGenerateBitcoins = fGenerate; - CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins); + WriteSetting("fGenerateBitcoins", fGenerateBitcoins); MainFrameRepaint(); } if (fGenerateBitcoins) @@ -3078,7 +3111,7 @@ void GenerateBitcoins(bool fGenerate) printf("Starting %d BitcoinMiner threads\n", nAddThreads); for (int i = 0; i < nAddThreads; i++) { - if (!CreateThread(ThreadBitcoinMiner, NULL)) + if (!CreateThread(ThreadBitcoinMiner, pwallet)) printf("Error: CreateThread(ThreadBitcoinMiner) failed\n"); Sleep(10); }