block index checking on load, extra redundant checks, misc refactoring
[novacoin.git] / main.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto\r
2 // Distributed under the MIT/X11 software license, see the accompanying\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
4 \r
5 #include "headers.h"\r
6 #include "cryptopp/sha.h"\r
7 \r
8 \r
9 \r
10 \r
11 \r
12 //\r
13 // Global state\r
14 //\r
15 \r
16 CCriticalSection cs_main;\r
17 \r
18 map<uint256, CTransaction> mapTransactions;\r
19 CCriticalSection cs_mapTransactions;\r
20 unsigned int nTransactionsUpdated = 0;\r
21 map<COutPoint, CInPoint> mapNextTx;\r
22 \r
23 map<uint256, CBlockIndex*> mapBlockIndex;\r
24 const uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");\r
25 CBlockIndex* pindexGenesisBlock = NULL;\r
26 int nBestHeight = -1;\r
27 CBigNum bnBestChainWork = 0;\r
28 CBigNum bnBestInvalidWork = 0;\r
29 uint256 hashBestChain = 0;\r
30 CBlockIndex* pindexBest = NULL;\r
31 int64 nTimeBestReceived = 0;\r
32 \r
33 map<uint256, CBlock*> mapOrphanBlocks;\r
34 multimap<uint256, CBlock*> mapOrphanBlocksByPrev;\r
35 \r
36 map<uint256, CDataStream*> mapOrphanTransactions;\r
37 multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;\r
38 \r
39 map<uint256, CWalletTx> mapWallet;\r
40 vector<uint256> vWalletUpdated;\r
41 CCriticalSection cs_mapWallet;\r
42 \r
43 map<vector<unsigned char>, CPrivKey> mapKeys;\r
44 map<uint160, vector<unsigned char> > mapPubKeys;\r
45 CCriticalSection cs_mapKeys;\r
46 CKey keyUser;\r
47 \r
48 map<uint256, int> mapRequestCount;\r
49 CCriticalSection cs_mapRequestCount;\r
50 \r
51 map<string, string> mapAddressBook;\r
52 CCriticalSection cs_mapAddressBook;\r
53 \r
54 vector<unsigned char> vchDefaultKey;\r
55 \r
56 double dHashesPerSec;\r
57 int64 nHPSTimerStart;\r
58 \r
59 // Settings\r
60 int fGenerateBitcoins = false;\r
61 int64 nTransactionFee = 0;\r
62 CAddress addrIncoming;\r
63 int fLimitProcessors = false;\r
64 int nLimitProcessors = 1;\r
65 int fMinimizeToTray = true;\r
66 int fMinimizeOnClose = true;\r
67 \r
68 \r
69 \r
70 \r
71 \r
72 \r
73 //////////////////////////////////////////////////////////////////////////////\r
74 //\r
75 // mapKeys\r
76 //\r
77 \r
78 bool AddKey(const CKey& key)\r
79 {\r
80     CRITICAL_BLOCK(cs_mapKeys)\r
81     {\r
82         mapKeys[key.GetPubKey()] = key.GetPrivKey();\r
83         mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();\r
84     }\r
85     return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());\r
86 }\r
87 \r
88 vector<unsigned char> GenerateNewKey()\r
89 {\r
90     RandAddSeedPerfmon();\r
91     CKey key;\r
92     key.MakeNewKey();\r
93     if (!AddKey(key))\r
94         throw runtime_error("GenerateNewKey() : AddKey failed\n");\r
95     return key.GetPubKey();\r
96 }\r
97 \r
98 \r
99 \r
100 \r
101 //////////////////////////////////////////////////////////////////////////////\r
102 //\r
103 // mapWallet\r
104 //\r
105 \r
106 bool AddToWallet(const CWalletTx& wtxIn)\r
107 {\r
108     uint256 hash = wtxIn.GetHash();\r
109     CRITICAL_BLOCK(cs_mapWallet)\r
110     {\r
111         // Inserts only if not already there, returns tx inserted or tx found\r
112         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));\r
113         CWalletTx& wtx = (*ret.first).second;\r
114         bool fInsertedNew = ret.second;\r
115         if (fInsertedNew)\r
116             wtx.nTimeReceived = GetAdjustedTime();\r
117 \r
118         bool fUpdated = false;\r
119         if (!fInsertedNew)\r
120         {\r
121             // Merge\r
122             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)\r
123             {\r
124                 wtx.hashBlock = wtxIn.hashBlock;\r
125                 fUpdated = true;\r
126             }\r
127             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))\r
128             {\r
129                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;\r
130                 wtx.nIndex = wtxIn.nIndex;\r
131                 fUpdated = true;\r
132             }\r
133             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)\r
134             {\r
135                 wtx.fFromMe = wtxIn.fFromMe;\r
136                 fUpdated = true;\r
137             }\r
138             if (wtxIn.fSpent && wtxIn.fSpent != wtx.fSpent)\r
139             {\r
140                 wtx.fSpent = wtxIn.fSpent;\r
141                 fUpdated = true;\r
142             }\r
143         }\r
144 \r
145         //// debug print\r
146         printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));\r
147 \r
148         // Write to disk\r
149         if (fInsertedNew || fUpdated)\r
150             if (!wtx.WriteToDisk())\r
151                 return false;\r
152 \r
153         // If default receiving address gets used, replace it with a new one\r
154         CScript scriptDefaultKey;\r
155         scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);\r
156         foreach(const CTxOut& txout, wtx.vout)\r
157         {\r
158             if (txout.scriptPubKey == scriptDefaultKey)\r
159             {\r
160                 CWalletDB walletdb;\r
161                 walletdb.WriteDefaultKey(GenerateNewKey());\r
162                 walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");\r
163             }\r
164         }\r
165 \r
166         // Notify UI\r
167         vWalletUpdated.push_back(hash);\r
168     }\r
169 \r
170     // Refresh UI\r
171     MainFrameRepaint();\r
172     return true;\r
173 }\r
174 \r
175 bool AddToWalletIfMine(const CTransaction& tx, const CBlock* pblock)\r
176 {\r
177     if (tx.IsMine() || mapWallet.count(tx.GetHash()))\r
178     {\r
179         CWalletTx wtx(tx);\r
180         // Get merkle branch if transaction was found in a block\r
181         if (pblock)\r
182             wtx.SetMerkleBranch(pblock);\r
183         return AddToWallet(wtx);\r
184     }\r
185     return true;\r
186 }\r
187 \r
188 bool EraseFromWallet(uint256 hash)\r
189 {\r
190     CRITICAL_BLOCK(cs_mapWallet)\r
191     {\r
192         if (mapWallet.erase(hash))\r
193             CWalletDB().EraseTx(hash);\r
194     }\r
195     return true;\r
196 }\r
197 \r
198 void WalletUpdateSpent(const COutPoint& prevout)\r
199 {\r
200     // Anytime a signature is successfully verified, it's proof the outpoint is spent.\r
201     // Update the wallet spent flag if it doesn't know due to wallet.dat being\r
202     // restored from backup or the user making copies of wallet.dat.\r
203     CRITICAL_BLOCK(cs_mapWallet)\r
204     {\r
205         map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);\r
206         if (mi != mapWallet.end())\r
207         {\r
208             CWalletTx& wtx = (*mi).second;\r
209             if (!wtx.fSpent && wtx.vout[prevout.n].IsMine())\r
210             {\r
211                 printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());\r
212                 wtx.fSpent = true;\r
213                 wtx.WriteToDisk();\r
214                 vWalletUpdated.push_back(prevout.hash);\r
215             }\r
216         }\r
217     }\r
218 }\r
219 \r
220 \r
221 \r
222 \r
223 \r
224 \r
225 \r
226 \r
227 //////////////////////////////////////////////////////////////////////////////\r
228 //\r
229 // mapOrphanTransactions\r
230 //\r
231 \r
232 void AddOrphanTx(const CDataStream& vMsg)\r
233 {\r
234     CTransaction tx;\r
235     CDataStream(vMsg) >> tx;\r
236     uint256 hash = tx.GetHash();\r
237     if (mapOrphanTransactions.count(hash))\r
238         return;\r
239     CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg);\r
240     foreach(const CTxIn& txin, tx.vin)\r
241         mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));\r
242 }\r
243 \r
244 void EraseOrphanTx(uint256 hash)\r
245 {\r
246     if (!mapOrphanTransactions.count(hash))\r
247         return;\r
248     const CDataStream* pvMsg = mapOrphanTransactions[hash];\r
249     CTransaction tx;\r
250     CDataStream(*pvMsg) >> tx;\r
251     foreach(const CTxIn& txin, tx.vin)\r
252     {\r
253         for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(txin.prevout.hash);\r
254              mi != mapOrphanTransactionsByPrev.upper_bound(txin.prevout.hash);)\r
255         {\r
256             if ((*mi).second == pvMsg)\r
257                 mapOrphanTransactionsByPrev.erase(mi++);\r
258             else\r
259                 mi++;\r
260         }\r
261     }\r
262     delete pvMsg;\r
263     mapOrphanTransactions.erase(hash);\r
264 }\r
265 \r
266 \r
267 \r
268 \r
269 \r
270 \r
271 \r
272 \r
273 //////////////////////////////////////////////////////////////////////////////\r
274 //\r
275 // CTransaction\r
276 //\r
277 \r
278 bool CTxIn::IsMine() const\r
279 {\r
280     CRITICAL_BLOCK(cs_mapWallet)\r
281     {\r
282         map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);\r
283         if (mi != mapWallet.end())\r
284         {\r
285             const CWalletTx& prev = (*mi).second;\r
286             if (prevout.n < prev.vout.size())\r
287                 if (prev.vout[prevout.n].IsMine())\r
288                     return true;\r
289         }\r
290     }\r
291     return false;\r
292 }\r
293 \r
294 int64 CTxIn::GetDebit() const\r
295 {\r
296     CRITICAL_BLOCK(cs_mapWallet)\r
297     {\r
298         map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);\r
299         if (mi != mapWallet.end())\r
300         {\r
301             const CWalletTx& prev = (*mi).second;\r
302             if (prevout.n < prev.vout.size())\r
303                 if (prev.vout[prevout.n].IsMine())\r
304                     return prev.vout[prevout.n].nValue;\r
305         }\r
306     }\r
307     return 0;\r
308 }\r
309 \r
310 int64 CWalletTx::GetTxTime() const\r
311 {\r
312     if (!fTimeReceivedIsTxTime && hashBlock != 0)\r
313     {\r
314         // If we did not receive the transaction directly, we rely on the block's\r
315         // time to figure out when it happened.  We use the median over a range\r
316         // of blocks to try to filter out inaccurate block times.\r
317         map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);\r
318         if (mi != mapBlockIndex.end())\r
319         {\r
320             CBlockIndex* pindex = (*mi).second;\r
321             if (pindex)\r
322                 return pindex->GetMedianTime();\r
323         }\r
324     }\r
325     return nTimeReceived;\r
326 }\r
327 \r
328 int CWalletTx::GetRequestCount() const\r
329 {\r
330     // Returns -1 if it wasn't being tracked\r
331     int nRequests = -1;\r
332     CRITICAL_BLOCK(cs_mapRequestCount)\r
333     {\r
334         if (IsCoinBase())\r
335         {\r
336             // Generated block\r
337             if (hashBlock != 0)\r
338             {\r
339                 map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);\r
340                 if (mi != mapRequestCount.end())\r
341                     nRequests = (*mi).second;\r
342             }\r
343         }\r
344         else\r
345         {\r
346             // Did anyone request this transaction?\r
347             map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());\r
348             if (mi != mapRequestCount.end())\r
349             {\r
350                 nRequests = (*mi).second;\r
351 \r
352                 // How about the block it's in?\r
353                 if (nRequests == 0 && hashBlock != 0)\r
354                 {\r
355                     map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);\r
356                     if (mi != mapRequestCount.end())\r
357                         nRequests = (*mi).second;\r
358                     else\r
359                         nRequests = 1; // If it's in someone else's block it must have got out\r
360                 }\r
361             }\r
362         }\r
363     }\r
364     return nRequests;\r
365 }\r
366 \r
367 \r
368 \r
369 \r
370 int CMerkleTx::SetMerkleBranch(const CBlock* pblock)\r
371 {\r
372     if (fClient)\r
373     {\r
374         if (hashBlock == 0)\r
375             return 0;\r
376     }\r
377     else\r
378     {\r
379         CBlock blockTmp;\r
380         if (pblock == NULL)\r
381         {\r
382             // Load the block this tx is in\r
383             CTxIndex txindex;\r
384             if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))\r
385                 return 0;\r
386             if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))\r
387                 return 0;\r
388             pblock = &blockTmp;\r
389         }\r
390 \r
391         // Update the tx's hashBlock\r
392         hashBlock = pblock->GetHash();\r
393 \r
394         // Locate the transaction\r
395         for (nIndex = 0; nIndex < pblock->vtx.size(); nIndex++)\r
396             if (pblock->vtx[nIndex] == *(CTransaction*)this)\r
397                 break;\r
398         if (nIndex == pblock->vtx.size())\r
399         {\r
400             vMerkleBranch.clear();\r
401             nIndex = -1;\r
402             printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");\r
403             return 0;\r
404         }\r
405 \r
406         // Fill in merkle branch\r
407         vMerkleBranch = pblock->GetMerkleBranch(nIndex);\r
408     }\r
409 \r
410     // Is the tx in a block that's in the main chain\r
411     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);\r
412     if (mi == mapBlockIndex.end())\r
413         return 0;\r
414     CBlockIndex* pindex = (*mi).second;\r
415     if (!pindex || !pindex->IsInMainChain())\r
416         return 0;\r
417 \r
418     return pindexBest->nHeight - pindex->nHeight + 1;\r
419 }\r
420 \r
421 \r
422 \r
423 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)\r
424 {\r
425     vtxPrev.clear();\r
426 \r
427     const int COPY_DEPTH = 3;\r
428     if (SetMerkleBranch() < COPY_DEPTH)\r
429     {\r
430         vector<uint256> vWorkQueue;\r
431         foreach(const CTxIn& txin, vin)\r
432             vWorkQueue.push_back(txin.prevout.hash);\r
433 \r
434         // This critsect is OK because txdb is already open\r
435         CRITICAL_BLOCK(cs_mapWallet)\r
436         {\r
437             map<uint256, const CMerkleTx*> mapWalletPrev;\r
438             set<uint256> setAlreadyDone;\r
439             for (int i = 0; i < vWorkQueue.size(); i++)\r
440             {\r
441                 uint256 hash = vWorkQueue[i];\r
442                 if (setAlreadyDone.count(hash))\r
443                     continue;\r
444                 setAlreadyDone.insert(hash);\r
445 \r
446                 CMerkleTx tx;\r
447                 if (mapWallet.count(hash))\r
448                 {\r
449                     tx = mapWallet[hash];\r
450                     foreach(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)\r
451                         mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;\r
452                 }\r
453                 else if (mapWalletPrev.count(hash))\r
454                 {\r
455                     tx = *mapWalletPrev[hash];\r
456                 }\r
457                 else if (!fClient && txdb.ReadDiskTx(hash, tx))\r
458                 {\r
459                     ;\r
460                 }\r
461                 else\r
462                 {\r
463                     printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");\r
464                     continue;\r
465                 }\r
466 \r
467                 int nDepth = tx.SetMerkleBranch();\r
468                 vtxPrev.push_back(tx);\r
469 \r
470                 if (nDepth < COPY_DEPTH)\r
471                     foreach(const CTxIn& txin, tx.vin)\r
472                         vWorkQueue.push_back(txin.prevout.hash);\r
473             }\r
474         }\r
475     }\r
476 \r
477     reverse(vtxPrev.begin(), vtxPrev.end());\r
478 }\r
479 \r
480 \r
481 \r
482 \r
483 \r
484 \r
485 \r
486 \r
487 \r
488 \r
489 \r
490 bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)\r
491 {\r
492     if (pfMissingInputs)\r
493         *pfMissingInputs = false;\r
494 \r
495     // Coinbase is only valid in a block, not as a loose transaction\r
496     if (IsCoinBase())\r
497         return error("AcceptTransaction() : coinbase as individual tx");\r
498 \r
499     if (!CheckTransaction())\r
500         return error("AcceptTransaction() : CheckTransaction failed");\r
501 \r
502     // To help v0.1.5 clients who would see it as a negative number\r
503     if ((int64)nLockTime > INT_MAX)\r
504         return error("AcceptTransaction() : not accepting nLockTime beyond 2038 yet");\r
505 \r
506     // Do we already have it?\r
507     uint256 hash = GetHash();\r
508     CRITICAL_BLOCK(cs_mapTransactions)\r
509         if (mapTransactions.count(hash))\r
510             return false;\r
511     if (fCheckInputs)\r
512         if (txdb.ContainsTx(hash))\r
513             return false;\r
514 \r
515     // Check for conflicts with in-memory transactions\r
516     CTransaction* ptxOld = NULL;\r
517     for (int i = 0; i < vin.size(); i++)\r
518     {\r
519         COutPoint outpoint = vin[i].prevout;\r
520         if (mapNextTx.count(outpoint))\r
521         {\r
522             // Disable replacement feature for now\r
523             return false;\r
524 \r
525             // Allow replacing with a newer version of the same transaction\r
526             if (i != 0)\r
527                 return false;\r
528             ptxOld = mapNextTx[outpoint].ptx;\r
529             if (!IsNewerThan(*ptxOld))\r
530                 return false;\r
531             for (int i = 0; i < vin.size(); i++)\r
532             {\r
533                 COutPoint outpoint = vin[i].prevout;\r
534                 if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)\r
535                     return false;\r
536             }\r
537             break;\r
538         }\r
539     }\r
540 \r
541     // Check against previous transactions\r
542     map<uint256, CTxIndex> mapUnused;\r
543     int64 nFees = 0;\r
544     if (fCheckInputs && !ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), pindexBest, nFees, false, false))\r
545     {\r
546         if (pfMissingInputs)\r
547             *pfMissingInputs = true;\r
548         return error("AcceptTransaction() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());\r
549     }\r
550 \r
551     // Store transaction in memory\r
552     CRITICAL_BLOCK(cs_mapTransactions)\r
553     {\r
554         if (ptxOld)\r
555         {\r
556             printf("AcceptTransaction() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());\r
557             ptxOld->RemoveFromMemoryPool();\r
558         }\r
559         AddToMemoryPool();\r
560     }\r
561 \r
562     ///// are we sure this is ok when loading transactions or restoring block txes\r
563     // If updated, erase old tx from wallet\r
564     if (ptxOld)\r
565         EraseFromWallet(ptxOld->GetHash());\r
566 \r
567     printf("AcceptTransaction(): accepted %s\n", hash.ToString().substr(0,6).c_str());\r
568     return true;\r
569 }\r
570 \r
571 \r
572 bool CTransaction::AddToMemoryPool()\r
573 {\r
574     // Add to memory pool without checking anything.  Don't call this directly,\r
575     // call AcceptTransaction to properly check the transaction first.\r
576     CRITICAL_BLOCK(cs_mapTransactions)\r
577     {\r
578         uint256 hash = GetHash();\r
579         mapTransactions[hash] = *this;\r
580         for (int i = 0; i < vin.size(); i++)\r
581             mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i);\r
582         nTransactionsUpdated++;\r
583     }\r
584     return true;\r
585 }\r
586 \r
587 \r
588 bool CTransaction::RemoveFromMemoryPool()\r
589 {\r
590     // Remove transaction from memory pool\r
591     CRITICAL_BLOCK(cs_mapTransactions)\r
592     {\r
593         foreach(const CTxIn& txin, vin)\r
594             mapNextTx.erase(txin.prevout);\r
595         mapTransactions.erase(GetHash());\r
596         nTransactionsUpdated++;\r
597     }\r
598     return true;\r
599 }\r
600 \r
601 \r
602 \r
603 \r
604 \r
605 \r
606 int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const\r
607 {\r
608     if (hashBlock == 0 || nIndex == -1)\r
609         return 0;\r
610 \r
611     // Find the block it claims to be in\r
612     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);\r
613     if (mi == mapBlockIndex.end())\r
614         return 0;\r
615     CBlockIndex* pindex = (*mi).second;\r
616     if (!pindex || !pindex->IsInMainChain())\r
617         return 0;\r
618 \r
619     // Make sure the merkle branch connects to this block\r
620     if (!fMerkleVerified)\r
621     {\r
622         if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)\r
623             return 0;\r
624         fMerkleVerified = true;\r
625     }\r
626 \r
627     nHeightRet = pindex->nHeight;\r
628     return pindexBest->nHeight - pindex->nHeight + 1;\r
629 }\r
630 \r
631 \r
632 int CMerkleTx::GetBlocksToMaturity() const\r
633 {\r
634     if (!IsCoinBase())\r
635         return 0;\r
636     return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());\r
637 }\r
638 \r
639 \r
640 bool CMerkleTx::AcceptTransaction(CTxDB& txdb, bool fCheckInputs)\r
641 {\r
642     if (fClient)\r
643     {\r
644         if (!IsInMainChain() && !ClientConnectInputs())\r
645             return false;\r
646         return CTransaction::AcceptTransaction(txdb, false);\r
647     }\r
648     else\r
649     {\r
650         return CTransaction::AcceptTransaction(txdb, fCheckInputs);\r
651     }\r
652 }\r
653 \r
654 \r
655 \r
656 bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)\r
657 {\r
658     CRITICAL_BLOCK(cs_mapTransactions)\r
659     {\r
660         foreach(CMerkleTx& tx, vtxPrev)\r
661         {\r
662             if (!tx.IsCoinBase())\r
663             {\r
664                 uint256 hash = tx.GetHash();\r
665                 if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))\r
666                     tx.AcceptTransaction(txdb, fCheckInputs);\r
667             }\r
668         }\r
669         if (!IsCoinBase())\r
670             return AcceptTransaction(txdb, fCheckInputs);\r
671     }\r
672     return true;\r
673 }\r
674 \r
675 void ReacceptWalletTransactions()\r
676 {\r
677     CTxDB txdb("r");\r
678     CRITICAL_BLOCK(cs_mapWallet)\r
679     {\r
680         foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)\r
681         {\r
682             CWalletTx& wtx = item.second;\r
683             if (wtx.fSpent && wtx.IsCoinBase())\r
684                 continue;\r
685 \r
686             CTxIndex txindex;\r
687             if (txdb.ReadTxIndex(wtx.GetHash(), txindex))\r
688             {\r
689                 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat\r
690                 if (!wtx.fSpent)\r
691                 {\r
692                     if (txindex.vSpent.size() != wtx.vout.size())\r
693                     {\r
694                         printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());\r
695                         continue;\r
696                     }\r
697                     for (int i = 0; i < txindex.vSpent.size(); i++)\r
698                     {\r
699                         if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())\r
700                         {\r
701                             printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());\r
702                             wtx.fSpent = true;\r
703                             wtx.WriteToDisk();\r
704                             break;\r
705                         }\r
706                     }\r
707                 }\r
708             }\r
709             else\r
710             {\r
711                 // Reaccept any txes of ours that aren't already in a block\r
712                 if (!wtx.IsCoinBase())\r
713                     wtx.AcceptWalletTransaction(txdb, false);\r
714             }\r
715         }\r
716     }\r
717 }\r
718 \r
719 \r
720 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)\r
721 {\r
722     foreach(const CMerkleTx& tx, vtxPrev)\r
723     {\r
724         if (!tx.IsCoinBase())\r
725         {\r
726             uint256 hash = tx.GetHash();\r
727             if (!txdb.ContainsTx(hash))\r
728                 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);\r
729         }\r
730     }\r
731     if (!IsCoinBase())\r
732     {\r
733         uint256 hash = GetHash();\r
734         if (!txdb.ContainsTx(hash))\r
735         {\r
736             printf("Relaying wtx %s\n", hash.ToString().substr(0,6).c_str());\r
737             RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);\r
738         }\r
739     }\r
740 }\r
741 \r
742 void ResendWalletTransactions()\r
743 {\r
744     // Do this infrequently and randomly to avoid giving away\r
745     // that these are our transactions.\r
746     static int64 nNextTime;\r
747     if (GetTime() < nNextTime)\r
748         return;\r
749     bool fFirst = (nNextTime == 0);\r
750     nNextTime = GetTime() + GetRand(30 * 60);\r
751     if (fFirst)\r
752         return;\r
753 \r
754     // Only do it if there's been a new block since last time\r
755     static int64 nLastTime;\r
756     if (nTimeBestReceived < nLastTime)\r
757         return;\r
758     nLastTime = GetTime();\r
759 \r
760     // Rebroadcast any of our txes that aren't in a block yet\r
761     printf("ResendWalletTransactions()\n");\r
762     CTxDB txdb("r");\r
763     CRITICAL_BLOCK(cs_mapWallet)\r
764     {\r
765         // Sort them in chronological order\r
766         multimap<unsigned int, CWalletTx*> mapSorted;\r
767         foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)\r
768         {\r
769             CWalletTx& wtx = item.second;\r
770             // Don't rebroadcast until it's had plenty of time that\r
771             // it should have gotten in already by now.\r
772             if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)\r
773                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));\r
774         }\r
775         foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)\r
776         {\r
777             CWalletTx& wtx = *item.second;\r
778             wtx.RelayWalletTransaction(txdb);\r
779         }\r
780     }\r
781 }\r
782 \r
783 \r
784 \r
785 \r
786 \r
787 \r
788 \r
789 \r
790 \r
791 \r
792 //////////////////////////////////////////////////////////////////////////////\r
793 //\r
794 // CBlock and CBlockIndex\r
795 //\r
796 \r
797 bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)\r
798 {\r
799     if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions))\r
800         return false;\r
801     if (GetHash() != pindex->GetBlockHash())\r
802         return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");\r
803     return true;\r
804 }\r
805 \r
806 uint256 GetOrphanRoot(const CBlock* pblock)\r
807 {\r
808     // Work back to the first block in the orphan chain\r
809     while (mapOrphanBlocks.count(pblock->hashPrevBlock))\r
810         pblock = mapOrphanBlocks[pblock->hashPrevBlock];\r
811     return pblock->GetHash();\r
812 }\r
813 \r
814 int64 CBlock::GetBlockValue(int nHeight, int64 nFees) const\r
815 {\r
816     int64 nSubsidy = 50 * COIN;\r
817 \r
818     // Subsidy is cut in half every 4 years\r
819     nSubsidy >>= (nHeight / 210000);\r
820 \r
821     return nSubsidy + nFees;\r
822 }\r
823 \r
824 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)\r
825 {\r
826     const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks\r
827     const int64 nTargetSpacing = 10 * 60;\r
828     const int64 nInterval = nTargetTimespan / nTargetSpacing;\r
829 \r
830     // Genesis block\r
831     if (pindexLast == NULL)\r
832         return bnProofOfWorkLimit.GetCompact();\r
833 \r
834     // Only change once per interval\r
835     if ((pindexLast->nHeight+1) % nInterval != 0)\r
836         return pindexLast->nBits;\r
837 \r
838     // Go back by what we want to be 14 days worth of blocks\r
839     const CBlockIndex* pindexFirst = pindexLast;\r
840     for (int i = 0; pindexFirst && i < nInterval-1; i++)\r
841         pindexFirst = pindexFirst->pprev;\r
842     assert(pindexFirst);\r
843 \r
844     // Limit adjustment step\r
845     int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();\r
846     printf("  nActualTimespan = %"PRI64d"  before bounds\n", nActualTimespan);\r
847     if (nActualTimespan < nTargetTimespan/4)\r
848         nActualTimespan = nTargetTimespan/4;\r
849     if (nActualTimespan > nTargetTimespan*4)\r
850         nActualTimespan = nTargetTimespan*4;\r
851 \r
852     // Retarget\r
853     CBigNum bnNew;\r
854     bnNew.SetCompact(pindexLast->nBits);\r
855     bnNew *= nActualTimespan;\r
856     bnNew /= nTargetTimespan;\r
857 \r
858     if (bnNew > bnProofOfWorkLimit)\r
859         bnNew = bnProofOfWorkLimit;\r
860 \r
861     /// debug print\r
862     printf("GetNextWorkRequired RETARGET\n");\r
863     printf("nTargetTimespan = %"PRI64d"    nActualTimespan = %"PRI64d"\n", nTargetTimespan, nActualTimespan);\r
864     printf("Before: %08x  %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str());\r
865     printf("After:  %08x  %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());\r
866 \r
867     return bnNew.GetCompact();\r
868 }\r
869 \r
870 bool CheckProofOfWork(uint256 hash, unsigned int nBits)\r
871 {\r
872     CBigNum bnTarget;\r
873     bnTarget.SetCompact(nBits);\r
874 \r
875     // Check range\r
876     if (bnTarget <= 0 || bnTarget > bnProofOfWorkLimit)\r
877         return error("CheckProofOfWork() : nBits below minimum work");\r
878 \r
879     // Check proof of work matches claimed amount\r
880     if (hash > bnTarget.getuint256())\r
881         return error("CheckProofOfWork() : hash doesn't match nBits");\r
882 \r
883     return true;\r
884 }\r
885 \r
886 bool IsInitialBlockDownload()\r
887 {\r
888     if (pindexBest == NULL)\r
889         return true;\r
890     static int64 nLastUpdate;\r
891     static CBlockIndex* pindexLastBest;\r
892     if (pindexBest != pindexLastBest)\r
893     {\r
894         pindexLastBest = pindexBest;\r
895         nLastUpdate = GetTime();\r
896     }\r
897     return (GetTime() - nLastUpdate < 10 &&\r
898             pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);\r
899 }\r
900 \r
901 bool IsLockdown()\r
902 {\r
903     if (!pindexBest)\r
904         return false;\r
905     return (bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6);\r
906 }\r
907 \r
908 void Lockdown(CBlockIndex* pindexNew)\r
909 {\r
910     if (pindexNew->bnChainWork > bnBestInvalidWork)\r
911     {\r
912         bnBestInvalidWork = pindexNew->bnChainWork;\r
913         CTxDB().WriteBestInvalidWork(bnBestInvalidWork);\r
914         MainFrameRepaint();\r
915     }\r
916     printf("Lockdown: invalid block=%s  height=%d  work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());\r
917     printf("Lockdown:  current best=%s  height=%d  work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());\r
918     printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0));\r
919     if (IsLockdown())\r
920         printf("Lockdown: WARNING: Displayed transactions may not be correct!  You may need to upgrade, or other nodes may need to upgrade.\n");\r
921 }\r
922 \r
923 \r
924 \r
925 \r
926 \r
927 \r
928 \r
929 \r
930 bool CTransaction::DisconnectInputs(CTxDB& txdb)\r
931 {\r
932     // Relinquish previous transactions' spent pointers\r
933     if (!IsCoinBase())\r
934     {\r
935         foreach(const CTxIn& txin, vin)\r
936         {\r
937             COutPoint prevout = txin.prevout;\r
938 \r
939             // Get prev txindex from disk\r
940             CTxIndex txindex;\r
941             if (!txdb.ReadTxIndex(prevout.hash, txindex))\r
942                 return error("DisconnectInputs() : ReadTxIndex failed");\r
943 \r
944             if (prevout.n >= txindex.vSpent.size())\r
945                 return error("DisconnectInputs() : prevout.n out of range");\r
946 \r
947             // Mark outpoint as not spent\r
948             txindex.vSpent[prevout.n].SetNull();\r
949 \r
950             // Write back\r
951             txdb.UpdateTxIndex(prevout.hash, txindex);\r
952         }\r
953     }\r
954 \r
955     // Remove transaction from index\r
956     if (!txdb.EraseTxIndex(*this))\r
957         return error("DisconnectInputs() : EraseTxPos failed");\r
958 \r
959     return true;\r
960 }\r
961 \r
962 \r
963 bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,\r
964                                  CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee)\r
965 {\r
966     // Take over previous transactions' spent pointers\r
967     if (!IsCoinBase())\r
968     {\r
969         int64 nValueIn = 0;\r
970         for (int i = 0; i < vin.size(); i++)\r
971         {\r
972             COutPoint prevout = vin[i].prevout;\r
973 \r
974             // Read txindex\r
975             CTxIndex txindex;\r
976             bool fFound = true;\r
977             if (fMiner && mapTestPool.count(prevout.hash))\r
978             {\r
979                 // Get txindex from current proposed changes\r
980                 txindex = mapTestPool[prevout.hash];\r
981             }\r
982             else\r
983             {\r
984                 // Read txindex from txdb\r
985                 fFound = txdb.ReadTxIndex(prevout.hash, txindex);\r
986             }\r
987             if (!fFound && (fBlock || fMiner))\r
988                 return fMiner ? false : error("ConnectInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,6).c_str(),  prevout.hash.ToString().substr(0,6).c_str());\r
989 \r
990             // Read txPrev\r
991             CTransaction txPrev;\r
992             if (!fFound || txindex.pos == CDiskTxPos(1,1,1))\r
993             {\r
994                 // Get prev tx from single transactions in memory\r
995                 CRITICAL_BLOCK(cs_mapTransactions)\r
996                 {\r
997                     if (!mapTransactions.count(prevout.hash))\r
998                         return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,6).c_str(),  prevout.hash.ToString().substr(0,6).c_str());\r
999                     txPrev = mapTransactions[prevout.hash];\r
1000                 }\r
1001                 if (!fFound)\r
1002                     txindex.vSpent.resize(txPrev.vout.size());\r
1003             }\r
1004             else\r
1005             {\r
1006                 // Get prev tx from disk\r
1007                 if (!txPrev.ReadFromDisk(txindex.pos))\r
1008                     return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,6).c_str(),  prevout.hash.ToString().substr(0,6).c_str());\r
1009             }\r
1010 \r
1011             if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())\r
1012                 return error("ConnectInputs() : %s prevout.n out of range %d %d %d prev tx %s\n%s", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,6).c_str(), txPrev.ToString().c_str());\r
1013 \r
1014             // If prev is coinbase, check that it's matured\r
1015             if (txPrev.IsCoinBase())\r
1016                 for (CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < COINBASE_MATURITY; pindex = pindex->pprev)\r
1017                     if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)\r
1018                         return error("ConnectInputs() : tried to spend coinbase at depth %d", pindexBlock->nHeight - pindex->nHeight);\r
1019 \r
1020             // Verify signature\r
1021             if (!VerifySignature(txPrev, *this, i))\r
1022                 return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,6).c_str());\r
1023 \r
1024             // Check for conflicts\r
1025             if (!txindex.vSpent[prevout.n].IsNull())\r
1026                 return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,6).c_str(), txindex.vSpent[prevout.n].ToString().c_str());\r
1027 \r
1028             // Mark outpoints as spent\r
1029             txindex.vSpent[prevout.n] = posThisTx;\r
1030 \r
1031             // Write back\r
1032             if (fBlock)\r
1033                 txdb.UpdateTxIndex(prevout.hash, txindex);\r
1034             else if (fMiner)\r
1035                 mapTestPool[prevout.hash] = txindex;\r
1036 \r
1037             nValueIn += txPrev.vout[prevout.n].nValue;\r
1038 \r
1039             // Check for negative or overflow input values\r
1040             if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))\r
1041                 return error("ConnectInputs() : txin values out of range");\r
1042         }\r
1043 \r
1044         if (nValueIn < GetValueOut())\r
1045             return error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,6).c_str());\r
1046 \r
1047         // Tally transaction fees\r
1048         int64 nTxFee = nValueIn - GetValueOut();\r
1049         if (nTxFee < 0)\r
1050             return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,6).c_str());\r
1051         if (nTxFee < nMinFee)\r
1052             return false;\r
1053         nFees += nTxFee;\r
1054     }\r
1055 \r
1056     if (fBlock)\r
1057     {\r
1058         // Add transaction to disk index\r
1059         if (!txdb.AddTxIndex(*this, posThisTx, pindexBlock->nHeight))\r
1060             return error("ConnectInputs() : AddTxPos failed");\r
1061     }\r
1062     else if (fMiner)\r
1063     {\r
1064         // Add transaction to test pool\r
1065         mapTestPool[GetHash()] = CTxIndex(CDiskTxPos(1,1,1), vout.size());\r
1066     }\r
1067 \r
1068     return true;\r
1069 }\r
1070 \r
1071 \r
1072 bool CTransaction::ClientConnectInputs()\r
1073 {\r
1074     if (IsCoinBase())\r
1075         return false;\r
1076 \r
1077     // Take over previous transactions' spent pointers\r
1078     CRITICAL_BLOCK(cs_mapTransactions)\r
1079     {\r
1080         int64 nValueIn = 0;\r
1081         for (int i = 0; i < vin.size(); i++)\r
1082         {\r
1083             // Get prev tx from single transactions in memory\r
1084             COutPoint prevout = vin[i].prevout;\r
1085             if (!mapTransactions.count(prevout.hash))\r
1086                 return false;\r
1087             CTransaction& txPrev = mapTransactions[prevout.hash];\r
1088 \r
1089             if (prevout.n >= txPrev.vout.size())\r
1090                 return false;\r
1091 \r
1092             // Verify signature\r
1093             if (!VerifySignature(txPrev, *this, i))\r
1094                 return error("ConnectInputs() : VerifySignature failed");\r
1095 \r
1096             ///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of\r
1097             ///// this has to go away now that posNext is gone\r
1098             // // Check for conflicts\r
1099             // if (!txPrev.vout[prevout.n].posNext.IsNull())\r
1100             //     return error("ConnectInputs() : prev tx already used");\r
1101             //\r
1102             // // Flag outpoints as used\r
1103             // txPrev.vout[prevout.n].posNext = posThisTx;\r
1104 \r
1105             nValueIn += txPrev.vout[prevout.n].nValue;\r
1106         }\r
1107         if (GetValueOut() > nValueIn)\r
1108             return false;\r
1109     }\r
1110 \r
1111     return true;\r
1112 }\r
1113 \r
1114 \r
1115 \r
1116 \r
1117 bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)\r
1118 {\r
1119     // Disconnect in reverse order\r
1120     for (int i = vtx.size()-1; i >= 0; i--)\r
1121         if (!vtx[i].DisconnectInputs(txdb))\r
1122             return false;\r
1123 \r
1124     // Update block index on disk without changing it in memory.\r
1125     // The memory index structure will be changed after the db commits.\r
1126     if (pindex->pprev)\r
1127     {\r
1128         CDiskBlockIndex blockindexPrev(pindex->pprev);\r
1129         blockindexPrev.hashNext = 0;\r
1130         txdb.WriteBlockIndex(blockindexPrev);\r
1131     }\r
1132 \r
1133     return true;\r
1134 }\r
1135 \r
1136 bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)\r
1137 {\r
1138     // Check it again in case a previous version let a bad block in\r
1139     if (!CheckBlock())\r
1140         return false;\r
1141 \r
1142     //// issue here: it doesn't know the version\r
1143     unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK) - 1 + GetSizeOfCompactSize(vtx.size());\r
1144 \r
1145     map<uint256, CTxIndex> mapUnused;\r
1146     int64 nFees = 0;\r
1147     foreach(CTransaction& tx, vtx)\r
1148     {\r
1149         CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);\r
1150         nTxPos += ::GetSerializeSize(tx, SER_DISK);\r
1151 \r
1152         if (!tx.ConnectInputs(txdb, mapUnused, posThisTx, pindex, nFees, true, false))\r
1153             return false;\r
1154     }\r
1155 \r
1156     if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))\r
1157         return false;\r
1158 \r
1159     // Update block index on disk without changing it in memory.\r
1160     // The memory index structure will be changed after the db commits.\r
1161     if (pindex->pprev)\r
1162     {\r
1163         CDiskBlockIndex blockindexPrev(pindex->pprev);\r
1164         blockindexPrev.hashNext = pindex->GetBlockHash();\r
1165         txdb.WriteBlockIndex(blockindexPrev);\r
1166     }\r
1167 \r
1168     // Watch for transactions paying to me\r
1169     foreach(CTransaction& tx, vtx)\r
1170         AddToWalletIfMine(tx, this);\r
1171 \r
1172     return true;\r
1173 }\r
1174 \r
1175 \r
1176 \r
1177 bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)\r
1178 {\r
1179     printf("REORGANIZE\n");\r
1180 \r
1181     // Find the fork\r
1182     CBlockIndex* pfork = pindexBest;\r
1183     CBlockIndex* plonger = pindexNew;\r
1184     while (pfork != plonger)\r
1185     {\r
1186         while (plonger->nHeight > pfork->nHeight)\r
1187             if (!(plonger = plonger->pprev))\r
1188                 return error("Reorganize() : plonger->pprev is null");\r
1189         if (pfork == plonger)\r
1190             break;\r
1191         if (!(pfork = pfork->pprev))\r
1192             return error("Reorganize() : pfork->pprev is null");\r
1193     }\r
1194 \r
1195     // List of what to disconnect\r
1196     vector<CBlockIndex*> vDisconnect;\r
1197     for (CBlockIndex* pindex = pindexBest; pindex != pfork; pindex = pindex->pprev)\r
1198         vDisconnect.push_back(pindex);\r
1199 \r
1200     // List of what to connect\r
1201     vector<CBlockIndex*> vConnect;\r
1202     for (CBlockIndex* pindex = pindexNew; pindex != pfork; pindex = pindex->pprev)\r
1203         vConnect.push_back(pindex);\r
1204     reverse(vConnect.begin(), vConnect.end());\r
1205 \r
1206     // Disconnect shorter branch\r
1207     vector<CTransaction> vResurrect;\r
1208     foreach(CBlockIndex* pindex, vDisconnect)\r
1209     {\r
1210         CBlock block;\r
1211         if (!block.ReadFromDisk(pindex))\r
1212             return error("Reorganize() : ReadFromDisk for disconnect failed");\r
1213         if (!block.DisconnectBlock(txdb, pindex))\r
1214             return error("Reorganize() : DisconnectBlock failed");\r
1215 \r
1216         // Queue memory transactions to resurrect\r
1217         foreach(const CTransaction& tx, block.vtx)\r
1218             if (!tx.IsCoinBase())\r
1219                 vResurrect.push_back(tx);\r
1220     }\r
1221 \r
1222     // Connect longer branch\r
1223     vector<CTransaction> vDelete;\r
1224     for (int i = 0; i < vConnect.size(); i++)\r
1225     {\r
1226         CBlockIndex* pindex = vConnect[i];\r
1227         CBlock block;\r
1228         if (!block.ReadFromDisk(pindex))\r
1229             return error("Reorganize() : ReadFromDisk for connect failed");\r
1230         if (!block.ConnectBlock(txdb, pindex))\r
1231         {\r
1232             // Invalid block\r
1233             txdb.TxnAbort();\r
1234             return error("Reorganize() : ConnectBlock failed");\r
1235         }\r
1236 \r
1237         // Queue memory transactions to delete\r
1238         foreach(const CTransaction& tx, block.vtx)\r
1239             vDelete.push_back(tx);\r
1240     }\r
1241     if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))\r
1242         return error("Reorganize() : WriteHashBestChain failed");\r
1243 \r
1244     // Commit now because resurrecting could take some time\r
1245     txdb.TxnCommit();\r
1246 \r
1247     // Disconnect shorter branch\r
1248     foreach(CBlockIndex* pindex, vDisconnect)\r
1249         if (pindex->pprev)\r
1250             pindex->pprev->pnext = NULL;\r
1251 \r
1252     // Connect longer branch\r
1253     foreach(CBlockIndex* pindex, vConnect)\r
1254         if (pindex->pprev)\r
1255             pindex->pprev->pnext = pindex;\r
1256 \r
1257     // Resurrect memory transactions that were in the disconnected branch\r
1258     foreach(CTransaction& tx, vResurrect)\r
1259         tx.AcceptTransaction(txdb, false);\r
1260 \r
1261     // Delete redundant memory transactions that are in the connected branch\r
1262     foreach(CTransaction& tx, vDelete)\r
1263         tx.RemoveFromMemoryPool();\r
1264 \r
1265     return true;\r
1266 }\r
1267 \r
1268 \r
1269 bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)\r
1270 {\r
1271     uint256 hash = GetHash();\r
1272 \r
1273     txdb.TxnBegin();\r
1274     if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)\r
1275     {\r
1276         pindexGenesisBlock = pindexNew;\r
1277         txdb.WriteHashBestChain(hash);\r
1278     }\r
1279     else if (hashPrevBlock == hashBestChain)\r
1280     {\r
1281         // Adding to current best branch\r
1282         if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))\r
1283         {\r
1284             txdb.TxnAbort();\r
1285             Lockdown(pindexNew);\r
1286             return error("SetBestChain() : ConnectBlock failed");\r
1287         }\r
1288         txdb.TxnCommit();\r
1289         pindexNew->pprev->pnext = pindexNew;\r
1290 \r
1291         // Delete redundant memory transactions\r
1292         foreach(CTransaction& tx, vtx)\r
1293             tx.RemoveFromMemoryPool();\r
1294     }\r
1295     else\r
1296     {\r
1297         // New best branch\r
1298         if (!Reorganize(txdb, pindexNew))\r
1299         {\r
1300             txdb.TxnAbort();\r
1301             Lockdown(pindexNew);\r
1302             return error("SetBestChain() : Reorganize failed");\r
1303         }\r
1304     }\r
1305     txdb.TxnCommit();\r
1306 \r
1307     // New best block\r
1308     hashBestChain = hash;\r
1309     pindexBest = pindexNew;\r
1310     nBestHeight = pindexBest->nHeight;\r
1311     bnBestChainWork = pindexNew->bnChainWork;\r
1312     nTimeBestReceived = GetTime();\r
1313     nTransactionsUpdated++;\r
1314     printf("SetBestChain: new best=%s  height=%d  work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());\r
1315 \r
1316     return true;\r
1317 }\r
1318 \r
1319 \r
1320 bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)\r
1321 {\r
1322     // Check for duplicate\r
1323     uint256 hash = GetHash();\r
1324     if (mapBlockIndex.count(hash))\r
1325         return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,20).c_str());\r
1326 \r
1327     // Construct new block index object\r
1328     CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);\r
1329     if (!pindexNew)\r
1330         return error("AddToBlockIndex() : new CBlockIndex failed");\r
1331     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;\r
1332     pindexNew->phashBlock = &((*mi).first);\r
1333     map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);\r
1334     if (miPrev != mapBlockIndex.end())\r
1335     {\r
1336         pindexNew->pprev = (*miPrev).second;\r
1337         pindexNew->nHeight = pindexNew->pprev->nHeight + 1;\r
1338     }\r
1339     pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork();\r
1340 \r
1341     CTxDB txdb;\r
1342     txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));\r
1343 \r
1344     // New best\r
1345     if (pindexNew->bnChainWork > bnBestChainWork)\r
1346         if (!SetBestChain(txdb, pindexNew))\r
1347             return false;\r
1348 \r
1349     txdb.Close();\r
1350 \r
1351     if (pindexNew == pindexBest)\r
1352     {\r
1353         // Notify UI to display prev block's coinbase if it was ours\r
1354         static uint256 hashPrevBestCoinBase;\r
1355         CRITICAL_BLOCK(cs_mapWallet)\r
1356             vWalletUpdated.push_back(hashPrevBestCoinBase);\r
1357         hashPrevBestCoinBase = vtx[0].GetHash();\r
1358     }\r
1359 \r
1360     MainFrameRepaint();\r
1361     return true;\r
1362 }\r
1363 \r
1364 \r
1365 \r
1366 \r
1367 bool CBlock::CheckBlock() const\r
1368 {\r
1369     // These are checks that are independent of context\r
1370     // that can be verified before saving an orphan block.\r
1371 \r
1372     // Size limits\r
1373     if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)\r
1374         return error("CheckBlock() : size limits failed");\r
1375 \r
1376     // Check timestamp\r
1377     if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)\r
1378         return error("CheckBlock() : block timestamp too far in the future");\r
1379 \r
1380     // First transaction must be coinbase, the rest must not be\r
1381     if (vtx.empty() || !vtx[0].IsCoinBase())\r
1382         return error("CheckBlock() : first tx is not coinbase");\r
1383     for (int i = 1; i < vtx.size(); i++)\r
1384         if (vtx[i].IsCoinBase())\r
1385             return error("CheckBlock() : more than one coinbase");\r
1386 \r
1387     // Check transactions\r
1388     foreach(const CTransaction& tx, vtx)\r
1389         if (!tx.CheckTransaction())\r
1390             return error("CheckBlock() : CheckTransaction failed");\r
1391 \r
1392     // Check proof of work matches claimed amount\r
1393     if (!CheckProofOfWork(GetHash(), nBits))\r
1394         return error("CheckBlock() : proof of work failed");\r
1395 \r
1396     // Check merkleroot\r
1397     if (hashMerkleRoot != BuildMerkleTree())\r
1398         return error("CheckBlock() : hashMerkleRoot mismatch");\r
1399 \r
1400     return true;\r
1401 }\r
1402 \r
1403 bool CBlock::AcceptBlock()\r
1404 {\r
1405     // Check for duplicate\r
1406     uint256 hash = GetHash();\r
1407     if (mapBlockIndex.count(hash))\r
1408         return error("AcceptBlock() : block already in mapBlockIndex");\r
1409 \r
1410     // Get prev block index\r
1411     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);\r
1412     if (mi == mapBlockIndex.end())\r
1413         return error("AcceptBlock() : prev block not found");\r
1414     CBlockIndex* pindexPrev = (*mi).second;\r
1415 \r
1416     // Check timestamp against prev\r
1417     if (GetBlockTime() <= pindexPrev->GetMedianTimePast())\r
1418         return error("AcceptBlock() : block's timestamp is too early");\r
1419 \r
1420     // Check that all transactions are finalized\r
1421     foreach(const CTransaction& tx, vtx)\r
1422         if (!tx.IsFinal(pindexPrev->nHeight+1, GetBlockTime()))\r
1423             return error("AcceptBlock() : contains a non-final transaction");\r
1424 \r
1425     // Check proof of work\r
1426     if (nBits != GetNextWorkRequired(pindexPrev))\r
1427         return error("AcceptBlock() : incorrect proof of work");\r
1428 \r
1429     // Check that the block chain matches the known block chain up to a checkpoint\r
1430     if ((pindexPrev->nHeight+1 == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||\r
1431         (pindexPrev->nHeight+1 == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||\r
1432         (pindexPrev->nHeight+1 == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||\r
1433         (pindexPrev->nHeight+1 == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||\r
1434         (pindexPrev->nHeight+1 == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))\r
1435         return error("AcceptBlock() : rejected by checkpoint lockin at %d", pindexPrev->nHeight+1);\r
1436 \r
1437     // Scanback checkpoint lockin\r
1438     for (CBlockIndex* pindex = pindexPrev; pindex->nHeight >= 74000; pindex = pindex->pprev)\r
1439     {\r
1440         if (pindex->nHeight == 74000 && pindex->GetBlockHash() != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))\r
1441             return error("AcceptBlock() : rejected by scanback lockin at %d", pindex->nHeight);\r
1442         if (pindex->nHeight == 74638 && pindex->GetBlockHash() == uint256("0x0000000000790ab3f22ec756ad43b6ab569abf0bddeb97c67a6f7b1470a7ec1c"))\r
1443             return error("AcceptBlock() : rejected by scanback lockin at %d", pindex->nHeight);\r
1444     }\r
1445 \r
1446     // Write block to history file\r
1447     if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))\r
1448         return error("AcceptBlock() : out of disk space");\r
1449     unsigned int nFile;\r
1450     unsigned int nBlockPos;\r
1451     if (!WriteToDisk(!fClient, nFile, nBlockPos))\r
1452         return error("AcceptBlock() : WriteToDisk failed");\r
1453     if (!AddToBlockIndex(nFile, nBlockPos))\r
1454         return error("AcceptBlock() : AddToBlockIndex failed");\r
1455 \r
1456     // Relay inventory, but don't relay old inventory during initial block download\r
1457     if (hashBestChain == hash)\r
1458         CRITICAL_BLOCK(cs_vNodes)\r
1459             foreach(CNode* pnode, vNodes)\r
1460                 if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 55000))\r
1461                     pnode->PushInventory(CInv(MSG_BLOCK, hash));\r
1462 \r
1463     return true;\r
1464 }\r
1465 \r
1466 bool ProcessBlock(CNode* pfrom, CBlock* pblock)\r
1467 {\r
1468     // Check for duplicate\r
1469     uint256 hash = pblock->GetHash();\r
1470     if (mapBlockIndex.count(hash))\r
1471         return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,20).c_str());\r
1472     if (mapOrphanBlocks.count(hash))\r
1473         return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,20).c_str());\r
1474 \r
1475     // Preliminary checks\r
1476     if (!pblock->CheckBlock())\r
1477     {\r
1478         delete pblock;\r
1479         return error("ProcessBlock() : CheckBlock FAILED");\r
1480     }\r
1481 \r
1482     // If don't already have its previous block, shunt it off to holding area until we get it\r
1483     if (!mapBlockIndex.count(pblock->hashPrevBlock))\r
1484     {\r
1485         printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str());\r
1486         mapOrphanBlocks.insert(make_pair(hash, pblock));\r
1487         mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));\r
1488 \r
1489         // Ask this guy to fill in what we're missing\r
1490         if (pfrom)\r
1491             pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock));\r
1492         return true;\r
1493     }\r
1494 \r
1495     // Store to disk\r
1496     if (!pblock->AcceptBlock())\r
1497     {\r
1498         delete pblock;\r
1499         return error("ProcessBlock() : AcceptBlock FAILED");\r
1500     }\r
1501     delete pblock;\r
1502 \r
1503     // Recursively process any orphan blocks that depended on this one\r
1504     vector<uint256> vWorkQueue;\r
1505     vWorkQueue.push_back(hash);\r
1506     for (int i = 0; i < vWorkQueue.size(); i++)\r
1507     {\r
1508         uint256 hashPrev = vWorkQueue[i];\r
1509         for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);\r
1510              mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);\r
1511              ++mi)\r
1512         {\r
1513             CBlock* pblockOrphan = (*mi).second;\r
1514             if (pblockOrphan->AcceptBlock())\r
1515                 vWorkQueue.push_back(pblockOrphan->GetHash());\r
1516             mapOrphanBlocks.erase(pblockOrphan->GetHash());\r
1517             delete pblockOrphan;\r
1518         }\r
1519         mapOrphanBlocksByPrev.erase(hashPrev);\r
1520     }\r
1521 \r
1522     printf("ProcessBlock: ACCEPTED\n");\r
1523     return true;\r
1524 }\r
1525 \r
1526 \r
1527 \r
1528 \r
1529 \r
1530 \r
1531 \r
1532 \r
1533 template<typename Stream>\r
1534 bool ScanMessageStart(Stream& s)\r
1535 {\r
1536     // Scan ahead to the next pchMessageStart, which should normally be immediately\r
1537     // at the file pointer.  Leaves file pointer at end of pchMessageStart.\r
1538     s.clear(0);\r
1539     short prevmask = s.exceptions(0);\r
1540     const char* p = BEGIN(pchMessageStart);\r
1541     try\r
1542     {\r
1543         loop\r
1544         {\r
1545             char c;\r
1546             s.read(&c, 1);\r
1547             if (s.fail())\r
1548             {\r
1549                 s.clear(0);\r
1550                 s.exceptions(prevmask);\r
1551                 return false;\r
1552             }\r
1553             if (*p != c)\r
1554                 p = BEGIN(pchMessageStart);\r
1555             if (*p == c)\r
1556             {\r
1557                 if (++p == END(pchMessageStart))\r
1558                 {\r
1559                     s.clear(0);\r
1560                     s.exceptions(prevmask);\r
1561                     return true;\r
1562                 }\r
1563             }\r
1564         }\r
1565     }\r
1566     catch (...)\r
1567     {\r
1568         s.clear(0);\r
1569         s.exceptions(prevmask);\r
1570         return false;\r
1571     }\r
1572 }\r
1573 \r
1574 bool CheckDiskSpace(int64 nAdditionalBytes)\r
1575 {\r
1576     uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;\r
1577 \r
1578     // Check for 15MB because database could create another 10MB log file at any time\r
1579     if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes)\r
1580     {\r
1581         fShutdown = true;\r
1582         printf("***  %s***\n", _("Warning: Disk space is low  "));\r
1583 #ifdef GUI\r
1584         ThreadSafeMessageBox(_("Warning: Disk space is low  "), "Bitcoin", wxOK | wxICON_EXCLAMATION);\r
1585 #endif\r
1586         CreateThread(Shutdown, NULL);\r
1587         return false;\r
1588     }\r
1589     return true;\r
1590 }\r
1591 \r
1592 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode)\r
1593 {\r
1594     if (nFile == -1)\r
1595         return NULL;\r
1596     FILE* file = fopen(strprintf("%s/blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);\r
1597     if (!file)\r
1598         return NULL;\r
1599     if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))\r
1600     {\r
1601         if (fseek(file, nBlockPos, SEEK_SET) != 0)\r
1602         {\r
1603             fclose(file);\r
1604             return NULL;\r
1605         }\r
1606     }\r
1607     return file;\r
1608 }\r
1609 \r
1610 static unsigned int nCurrentBlockFile = 1;\r
1611 \r
1612 FILE* AppendBlockFile(unsigned int& nFileRet)\r
1613 {\r
1614     nFileRet = 0;\r
1615     loop\r
1616     {\r
1617         FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab");\r
1618         if (!file)\r
1619             return NULL;\r
1620         if (fseek(file, 0, SEEK_END) != 0)\r
1621             return NULL;\r
1622         // FAT32 filesize max 4GB, fseek and ftell max 2GB, so we must stay under 2GB\r
1623         if (ftell(file) < 0x7F000000 - MAX_SIZE)\r
1624         {\r
1625             nFileRet = nCurrentBlockFile;\r
1626             return file;\r
1627         }\r
1628         fclose(file);\r
1629         nCurrentBlockFile++;\r
1630     }\r
1631 }\r
1632 \r
1633 bool LoadBlockIndex(bool fAllowNew)\r
1634 {\r
1635     //\r
1636     // Load block index\r
1637     //\r
1638     CTxDB txdb("cr");\r
1639     if (!txdb.LoadBlockIndex())\r
1640         return false;\r
1641     txdb.Close();\r
1642 \r
1643     //\r
1644     // Init with genesis block\r
1645     //\r
1646     if (mapBlockIndex.empty())\r
1647     {\r
1648         if (!fAllowNew)\r
1649             return false;\r
1650 \r
1651 \r
1652         // Genesis Block:\r
1653         // GetHash()      = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f\r
1654         // hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b\r
1655         // txNew.vin[0].scriptSig     = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854\r
1656         // txNew.vout[0].nValue       = 5000000000\r
1657         // txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG\r
1658         // block.nVersion = 1\r
1659         // block.nTime    = 1231006505\r
1660         // block.nBits    = 0x1d00ffff\r
1661         // block.nNonce   = 2083236893\r
1662         // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)\r
1663         //   CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)\r
1664         //     CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)\r
1665         //     CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)\r
1666         //   vMerkleTree: 4a5e1e\r
1667 \r
1668         // Genesis block\r
1669         const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";\r
1670         CTransaction txNew;\r
1671         txNew.vin.resize(1);\r
1672         txNew.vout.resize(1);\r
1673         txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));\r
1674         txNew.vout[0].nValue = 50 * COIN;\r
1675         CBigNum bnPubKey;\r
1676         bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704");\r
1677         txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG;\r
1678         CBlock block;\r
1679         block.vtx.push_back(txNew);\r
1680         block.hashPrevBlock = 0;\r
1681         block.hashMerkleRoot = block.BuildMerkleTree();\r
1682         block.nVersion = 1;\r
1683         block.nTime    = 1231006505;\r
1684         block.nBits    = 0x1d00ffff;\r
1685         block.nNonce   = 2083236893;\r
1686 \r
1687             //// debug print\r
1688             printf("%s\n", block.GetHash().ToString().c_str());\r
1689             printf("%s\n", block.hashMerkleRoot.ToString().c_str());\r
1690             printf("%s\n", hashGenesisBlock.ToString().c_str());\r
1691             txNew.vout[0].scriptPubKey.print();\r
1692             block.print();\r
1693             assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));\r
1694 \r
1695         assert(block.GetHash() == hashGenesisBlock);\r
1696 \r
1697         // Start new block file\r
1698         unsigned int nFile;\r
1699         unsigned int nBlockPos;\r
1700         if (!block.WriteToDisk(!fClient, nFile, nBlockPos))\r
1701             return error("LoadBlockIndex() : writing genesis block to disk failed");\r
1702         if (!block.AddToBlockIndex(nFile, nBlockPos))\r
1703             return error("LoadBlockIndex() : genesis block not accepted");\r
1704     }\r
1705 \r
1706     return true;\r
1707 }\r
1708 \r
1709 \r
1710 \r
1711 void PrintBlockTree()\r
1712 {\r
1713     // precompute tree structure\r
1714     map<CBlockIndex*, vector<CBlockIndex*> > mapNext;\r
1715     for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)\r
1716     {\r
1717         CBlockIndex* pindex = (*mi).second;\r
1718         mapNext[pindex->pprev].push_back(pindex);\r
1719         // test\r
1720         //while (rand() % 3 == 0)\r
1721         //    mapNext[pindex->pprev].push_back(pindex);\r
1722     }\r
1723 \r
1724     vector<pair<int, CBlockIndex*> > vStack;\r
1725     vStack.push_back(make_pair(0, pindexGenesisBlock));\r
1726 \r
1727     int nPrevCol = 0;\r
1728     while (!vStack.empty())\r
1729     {\r
1730         int nCol = vStack.back().first;\r
1731         CBlockIndex* pindex = vStack.back().second;\r
1732         vStack.pop_back();\r
1733 \r
1734         // print split or gap\r
1735         if (nCol > nPrevCol)\r
1736         {\r
1737             for (int i = 0; i < nCol-1; i++)\r
1738                 printf("| ");\r
1739             printf("|\\\n");\r
1740         }\r
1741         else if (nCol < nPrevCol)\r
1742         {\r
1743             for (int i = 0; i < nCol; i++)\r
1744                 printf("| ");\r
1745             printf("|\n");\r
1746         }\r
1747         nPrevCol = nCol;\r
1748 \r
1749         // print columns\r
1750         for (int i = 0; i < nCol; i++)\r
1751             printf("| ");\r
1752 \r
1753         // print item\r
1754         CBlock block;\r
1755         block.ReadFromDisk(pindex);\r
1756         printf("%d (%u,%u) %s  %s  tx %d",\r
1757             pindex->nHeight,\r
1758             pindex->nFile,\r
1759             pindex->nBlockPos,\r
1760             block.GetHash().ToString().substr(0,20).c_str(),\r
1761             DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),\r
1762             block.vtx.size());\r
1763 \r
1764         CRITICAL_BLOCK(cs_mapWallet)\r
1765         {\r
1766             if (mapWallet.count(block.vtx[0].GetHash()))\r
1767             {\r
1768                 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];\r
1769                 printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());\r
1770             }\r
1771         }\r
1772         printf("\n");\r
1773 \r
1774 \r
1775         // put the main timechain first\r
1776         vector<CBlockIndex*>& vNext = mapNext[pindex];\r
1777         for (int i = 0; i < vNext.size(); i++)\r
1778         {\r
1779             if (vNext[i]->pnext)\r
1780             {\r
1781                 swap(vNext[0], vNext[i]);\r
1782                 break;\r
1783             }\r
1784         }\r
1785 \r
1786         // iterate children\r
1787         for (int i = 0; i < vNext.size(); i++)\r
1788             vStack.push_back(make_pair(nCol+i, vNext[i]));\r
1789     }\r
1790 }\r
1791 \r
1792 \r
1793 \r
1794 \r
1795 \r
1796 \r
1797 \r
1798 \r
1799 \r
1800 \r
1801 //////////////////////////////////////////////////////////////////////////////\r
1802 //\r
1803 // Messages\r
1804 //\r
1805 \r
1806 \r
1807 bool AlreadyHave(CTxDB& txdb, const CInv& inv)\r
1808 {\r
1809     switch (inv.type)\r
1810     {\r
1811     case MSG_TX:    return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);\r
1812     case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);\r
1813     }\r
1814     // Don't know what it is, just say we already got one\r
1815     return true;\r
1816 }\r
1817 \r
1818 \r
1819 \r
1820 \r
1821 \r
1822 \r
1823 \r
1824 bool ProcessMessages(CNode* pfrom)\r
1825 {\r
1826     CDataStream& vRecv = pfrom->vRecv;\r
1827     if (vRecv.empty())\r
1828         return true;\r
1829     //if (fDebug)\r
1830     //    printf("ProcessMessages(%d bytes)\n", vRecv.size());\r
1831 \r
1832     //\r
1833     // Message format\r
1834     //  (4) message start\r
1835     //  (12) command\r
1836     //  (4) size\r
1837     //  (4) checksum\r
1838     //  (x) data\r
1839     //\r
1840 \r
1841     loop\r
1842     {\r
1843         // Scan for message start\r
1844         CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));\r
1845         int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());\r
1846         if (vRecv.end() - pstart < nHeaderSize)\r
1847         {\r
1848             if (vRecv.size() > nHeaderSize)\r
1849             {\r
1850                 printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");\r
1851                 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);\r
1852             }\r
1853             break;\r
1854         }\r
1855         if (pstart - vRecv.begin() > 0)\r
1856             printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin());\r
1857         vRecv.erase(vRecv.begin(), pstart);\r
1858 \r
1859         // Read header\r
1860         vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);\r
1861         CMessageHeader hdr;\r
1862         vRecv >> hdr;\r
1863         if (!hdr.IsValid())\r
1864         {\r
1865             printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());\r
1866             continue;\r
1867         }\r
1868         string strCommand = hdr.GetCommand();\r
1869 \r
1870         // Message size\r
1871         unsigned int nMessageSize = hdr.nMessageSize;\r
1872         if (nMessageSize > vRecv.size())\r
1873         {\r
1874             // Rewind and wait for rest of message\r
1875             ///// need a mechanism to give up waiting for overlong message size error\r
1876             vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());\r
1877             break;\r
1878         }\r
1879 \r
1880         // Copy message to its own buffer\r
1881         CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);\r
1882         vRecv.ignore(nMessageSize);\r
1883 \r
1884         // Checksum\r
1885         if (vRecv.GetVersion() >= 209)\r
1886         {\r
1887             uint256 hash = Hash(vMsg.begin(), vMsg.end());\r
1888             unsigned int nChecksum = 0;\r
1889             memcpy(&nChecksum, &hash, sizeof(nChecksum));\r
1890             if (nChecksum != hdr.nChecksum)\r
1891             {\r
1892                 printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",\r
1893                        strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);\r
1894                 continue;\r
1895             }\r
1896         }\r
1897 \r
1898         // Process message\r
1899         bool fRet = false;\r
1900         try\r
1901         {\r
1902             CRITICAL_BLOCK(cs_main)\r
1903                 fRet = ProcessMessage(pfrom, strCommand, vMsg);\r
1904             if (fShutdown)\r
1905                 return true;\r
1906         }\r
1907         catch (std::ios_base::failure& e)\r
1908         {\r
1909             if (strstr(e.what(), "CDataStream::read() : end of data"))\r
1910             {\r
1911                 // Allow exceptions from underlength message on vRecv\r
1912                 printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());\r
1913             }\r
1914             else if (strstr(e.what(), ": size too large"))\r
1915             {\r
1916                 // Allow exceptions from overlong size\r
1917                 printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());\r
1918             }\r
1919             else\r
1920             {\r
1921                 PrintException(&e, "ProcessMessage()");\r
1922             }\r
1923         }\r
1924         catch (std::exception& e) {\r
1925             PrintException(&e, "ProcessMessage()");\r
1926         } catch (...) {\r
1927             PrintException(NULL, "ProcessMessage()");\r
1928         }\r
1929 \r
1930         if (!fRet)\r
1931             printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize);\r
1932     }\r
1933 \r
1934     vRecv.Compact();\r
1935     return true;\r
1936 }\r
1937 \r
1938 \r
1939 \r
1940 \r
1941 bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)\r
1942 {\r
1943     static map<unsigned int, vector<unsigned char> > mapReuseKey;\r
1944     RandAddSeedPerfmon();\r
1945     if (fDebug)\r
1946         printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());\r
1947     printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());\r
1948     if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)\r
1949     {\r
1950         printf("dropmessagestest DROPPING RECV MESSAGE\n");\r
1951         return true;\r
1952     }\r
1953 \r
1954 \r
1955 \r
1956 \r
1957 \r
1958     if (strCommand == "version")\r
1959     {\r
1960         // Each connection can only send one version message\r
1961         if (pfrom->nVersion != 0)\r
1962             return false;\r
1963 \r
1964         int64 nTime;\r
1965         CAddress addrMe;\r
1966         CAddress addrFrom;\r
1967         uint64 nNonce = 1;\r
1968         string strSubVer;\r
1969         vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;\r
1970         if (pfrom->nVersion == 10300)\r
1971             pfrom->nVersion = 300;\r
1972         if (pfrom->nVersion >= 106 && !vRecv.empty())\r
1973             vRecv >> addrFrom >> nNonce;\r
1974         if (pfrom->nVersion >= 106 && !vRecv.empty())\r
1975             vRecv >> strSubVer;\r
1976         if (pfrom->nVersion >= 209 && !vRecv.empty())\r
1977             vRecv >> pfrom->nStartingHeight;\r
1978 \r
1979         if (pfrom->nVersion == 0)\r
1980             return false;\r
1981 \r
1982         // Disconnect if we connected to ourself\r
1983         if (nNonce == nLocalHostNonce && nNonce > 1)\r
1984         {\r
1985             pfrom->fDisconnect = true;\r
1986             return true;\r
1987         }\r
1988 \r
1989         pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);\r
1990         if (pfrom->fClient)\r
1991         {\r
1992             pfrom->vSend.nType |= SER_BLOCKHEADERONLY;\r
1993             pfrom->vRecv.nType |= SER_BLOCKHEADERONLY;\r
1994         }\r
1995 \r
1996         AddTimeData(pfrom->addr.ip, nTime);\r
1997 \r
1998         // Change version\r
1999         if (pfrom->nVersion >= 209)\r
2000             pfrom->PushMessage("verack");\r
2001         pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));\r
2002         if (pfrom->nVersion < 209)\r
2003             pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));\r
2004 \r
2005         // Ask the first connected node for block updates\r
2006         static int nAskedForBlocks;\r
2007         if (!pfrom->fClient && (nAskedForBlocks < 1 || vNodes.size() <= 1))\r
2008         {\r
2009             nAskedForBlocks++;\r
2010             pfrom->PushGetBlocks(pindexBest, uint256(0));\r
2011         }\r
2012 \r
2013         pfrom->fSuccessfullyConnected = true;\r
2014 \r
2015         printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);\r
2016     }\r
2017 \r
2018 \r
2019     else if (pfrom->nVersion == 0)\r
2020     {\r
2021         // Must have a version message before anything else\r
2022         return false;\r
2023     }\r
2024 \r
2025 \r
2026     else if (strCommand == "verack")\r
2027     {\r
2028         pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));\r
2029     }\r
2030 \r
2031 \r
2032     else if (strCommand == "addr")\r
2033     {\r
2034         vector<CAddress> vAddr;\r
2035         vRecv >> vAddr;\r
2036         if (pfrom->nVersion < 200) // don't want addresses from 0.1.5\r
2037             return true;\r
2038         if (pfrom->nVersion < 209 && mapAddresses.size() > 1000) // don't want addr from 0.2.0 unless seeding\r
2039             return true;\r
2040         if (vAddr.size() > 1000)\r
2041             return error("message addr size() = %d", vAddr.size());\r
2042 \r
2043         // Store the new addresses\r
2044         foreach(CAddress& addr, vAddr)\r
2045         {\r
2046             if (fShutdown)\r
2047                 return true;\r
2048             // ignore IPv6 for now, since it isn't implemented anyway\r
2049             if (!addr.IsIPv4())\r
2050                 continue;\r
2051             addr.nTime = GetAdjustedTime() - 2 * 60 * 60;\r
2052             if (pfrom->fGetAddr || vAddr.size() > 10)\r
2053                 addr.nTime -= 5 * 24 * 60 * 60;\r
2054             AddAddress(addr);\r
2055             pfrom->AddAddressKnown(addr);\r
2056             if (!pfrom->fGetAddr && addr.IsRoutable())\r
2057             {\r
2058                 // Relay to a limited number of other nodes\r
2059                 CRITICAL_BLOCK(cs_vNodes)\r
2060                 {\r
2061                     // Use deterministic randomness to send to\r
2062                     // the same places for 12 hours at a time\r
2063                     static uint256 hashSalt;\r
2064                     if (hashSalt == 0)\r
2065                         RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));\r
2066                     uint256 hashRand = addr.ip ^ ((GetTime()+addr.ip)/(12*60*60)) ^ hashSalt;\r
2067                     multimap<uint256, CNode*> mapMix;\r
2068                     foreach(CNode* pnode, vNodes)\r
2069                         mapMix.insert(make_pair(hashRand = Hash(BEGIN(hashRand), END(hashRand)), pnode));\r
2070                     int nRelayNodes = 4;\r
2071                     for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)\r
2072                         ((*mi).second)->PushAddress(addr);\r
2073                 }\r
2074             }\r
2075         }\r
2076         if (vAddr.size() < 1000)\r
2077             pfrom->fGetAddr = false;\r
2078     }\r
2079 \r
2080 \r
2081     else if (strCommand == "inv")\r
2082     {\r
2083         vector<CInv> vInv;\r
2084         vRecv >> vInv;\r
2085         if (vInv.size() > 50000)\r
2086             return error("message inv size() = %d", vInv.size());\r
2087 \r
2088         CTxDB txdb("r");\r
2089         foreach(const CInv& inv, vInv)\r
2090         {\r
2091             if (fShutdown)\r
2092                 return true;\r
2093             pfrom->AddInventoryKnown(inv);\r
2094 \r
2095             bool fAlreadyHave = AlreadyHave(txdb, inv);\r
2096             printf("  got inventory: %s  %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");\r
2097 \r
2098             if (!fAlreadyHave)\r
2099                 pfrom->AskFor(inv);\r
2100             else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))\r
2101                 pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));\r
2102 \r
2103             // Track requests for our stuff\r
2104             CRITICAL_BLOCK(cs_mapRequestCount)\r
2105             {\r
2106                 map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);\r
2107                 if (mi != mapRequestCount.end())\r
2108                     (*mi).second++;\r
2109             }\r
2110         }\r
2111     }\r
2112 \r
2113 \r
2114     else if (strCommand == "getdata")\r
2115     {\r
2116         vector<CInv> vInv;\r
2117         vRecv >> vInv;\r
2118         if (vInv.size() > 50000)\r
2119             return error("message getdata size() = %d", vInv.size());\r
2120 \r
2121         foreach(const CInv& inv, vInv)\r
2122         {\r
2123             if (fShutdown)\r
2124                 return true;\r
2125             printf("received getdata for: %s\n", inv.ToString().c_str());\r
2126 \r
2127             if (inv.type == MSG_BLOCK)\r
2128             {\r
2129                 // Send block from disk\r
2130                 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);\r
2131                 if (mi != mapBlockIndex.end())\r
2132                 {\r
2133                     //// could optimize this to send header straight from blockindex for client\r
2134                     CBlock block;\r
2135                     block.ReadFromDisk((*mi).second, !pfrom->fClient);\r
2136                     pfrom->PushMessage("block", block);\r
2137 \r
2138                     // Trigger them to send a getblocks request for the next batch of inventory\r
2139                     if (inv.hash == pfrom->hashContinue)\r
2140                     {\r
2141                         // Bypass PushInventory, this must send even if redundant,\r
2142                         // and we want it right after the last block so they don't\r
2143                         // wait for other stuff first.\r
2144                         vector<CInv> vInv;\r
2145                         vInv.push_back(CInv(MSG_BLOCK, hashBestChain));\r
2146                         pfrom->PushMessage("inv", vInv);\r
2147                         pfrom->hashContinue = 0;\r
2148                     }\r
2149                 }\r
2150             }\r
2151             else if (inv.IsKnownType())\r
2152             {\r
2153                 // Send stream from relay memory\r
2154                 CRITICAL_BLOCK(cs_mapRelay)\r
2155                 {\r
2156                     map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);\r
2157                     if (mi != mapRelay.end())\r
2158                         pfrom->PushMessage(inv.GetCommand(), (*mi).second);\r
2159                 }\r
2160             }\r
2161 \r
2162             // Track requests for our stuff\r
2163             CRITICAL_BLOCK(cs_mapRequestCount)\r
2164             {\r
2165                 map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);\r
2166                 if (mi != mapRequestCount.end())\r
2167                     (*mi).second++;\r
2168             }\r
2169         }\r
2170     }\r
2171 \r
2172 \r
2173     else if (strCommand == "getblocks")\r
2174     {\r
2175         CBlockLocator locator;\r
2176         uint256 hashStop;\r
2177         vRecv >> locator >> hashStop;\r
2178 \r
2179         // Find the first block the caller has in the main chain\r
2180         CBlockIndex* pindex = locator.GetBlockIndex();\r
2181 \r
2182         // Send the rest of the chain\r
2183         if (pindex)\r
2184             pindex = pindex->pnext;\r
2185         int nLimit = 500 + locator.GetDistanceBack();\r
2186         printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);\r
2187         for (; pindex; pindex = pindex->pnext)\r
2188         {\r
2189             if (pindex->GetBlockHash() == hashStop)\r
2190             {\r
2191                 printf("  getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());\r
2192                 break;\r
2193             }\r
2194             pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));\r
2195             if (--nLimit <= 0)\r
2196             {\r
2197                 // When this block is requested, we'll send an inv that'll make them\r
2198                 // getblocks the next batch of inventory.\r
2199                 printf("  getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());\r
2200                 pfrom->hashContinue = pindex->GetBlockHash();\r
2201                 break;\r
2202             }\r
2203         }\r
2204     }\r
2205 \r
2206 \r
2207     else if (strCommand == "tx")\r
2208     {\r
2209         vector<uint256> vWorkQueue;\r
2210         CDataStream vMsg(vRecv);\r
2211         CTransaction tx;\r
2212         vRecv >> tx;\r
2213 \r
2214         CInv inv(MSG_TX, tx.GetHash());\r
2215         pfrom->AddInventoryKnown(inv);\r
2216 \r
2217         bool fMissingInputs = false;\r
2218         if (tx.AcceptTransaction(true, &fMissingInputs))\r
2219         {\r
2220             AddToWalletIfMine(tx, NULL);\r
2221             RelayMessage(inv, vMsg);\r
2222             mapAlreadyAskedFor.erase(inv);\r
2223             vWorkQueue.push_back(inv.hash);\r
2224 \r
2225             // Recursively process any orphan transactions that depended on this one\r
2226             for (int i = 0; i < vWorkQueue.size(); i++)\r
2227             {\r
2228                 uint256 hashPrev = vWorkQueue[i];\r
2229                 for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(hashPrev);\r
2230                      mi != mapOrphanTransactionsByPrev.upper_bound(hashPrev);\r
2231                      ++mi)\r
2232                 {\r
2233                     const CDataStream& vMsg = *((*mi).second);\r
2234                     CTransaction tx;\r
2235                     CDataStream(vMsg) >> tx;\r
2236                     CInv inv(MSG_TX, tx.GetHash());\r
2237 \r
2238                     if (tx.AcceptTransaction(true))\r
2239                     {\r
2240                         printf("   accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());\r
2241                         AddToWalletIfMine(tx, NULL);\r
2242                         RelayMessage(inv, vMsg);\r
2243                         mapAlreadyAskedFor.erase(inv);\r
2244                         vWorkQueue.push_back(inv.hash);\r
2245                     }\r
2246                 }\r
2247             }\r
2248 \r
2249             foreach(uint256 hash, vWorkQueue)\r
2250                 EraseOrphanTx(hash);\r
2251         }\r
2252         else if (fMissingInputs)\r
2253         {\r
2254             printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());\r
2255             AddOrphanTx(vMsg);\r
2256         }\r
2257     }\r
2258 \r
2259 \r
2260     else if (strCommand == "block")\r
2261     {\r
2262         auto_ptr<CBlock> pblock(new CBlock);\r
2263         vRecv >> *pblock;\r
2264 \r
2265         //// debug print\r
2266         printf("received block %s\n", pblock->GetHash().ToString().substr(0,20).c_str());\r
2267         // pblock->print();\r
2268 \r
2269         CInv inv(MSG_BLOCK, pblock->GetHash());\r
2270         pfrom->AddInventoryKnown(inv);\r
2271 \r
2272         if (ProcessBlock(pfrom, pblock.release()))\r
2273             mapAlreadyAskedFor.erase(inv);\r
2274     }\r
2275 \r
2276 \r
2277     else if (strCommand == "getaddr")\r
2278     {\r
2279         // This includes all nodes that are currently online,\r
2280         // since they rebroadcast an addr every 24 hours\r
2281         pfrom->vAddrToSend.clear();\r
2282         int64 nSince = GetAdjustedTime() - 12 * 60 * 60; // in the last 12 hours\r
2283         CRITICAL_BLOCK(cs_mapAddresses)\r
2284         {\r
2285             unsigned int nSize = mapAddresses.size();\r
2286             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)\r
2287             {\r
2288                 if (fShutdown)\r
2289                     return true;\r
2290                 const CAddress& addr = item.second;\r
2291                 if (addr.nTime > nSince)\r
2292                     pfrom->PushAddress(addr);\r
2293             }\r
2294         }\r
2295     }\r
2296 \r
2297 \r
2298     else if (strCommand == "checkorder")\r
2299     {\r
2300         uint256 hashReply;\r
2301         CWalletTx order;\r
2302         vRecv >> hashReply >> order;\r
2303 \r
2304         /// we have a chance to check the order here\r
2305 \r
2306         // Keep giving the same key to the same ip until they use it\r
2307         if (!mapReuseKey.count(pfrom->addr.ip))\r
2308             mapReuseKey[pfrom->addr.ip] = GenerateNewKey();\r
2309 \r
2310         // Send back approval of order and pubkey to use\r
2311         CScript scriptPubKey;\r
2312         scriptPubKey << mapReuseKey[pfrom->addr.ip] << OP_CHECKSIG;\r
2313         pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey);\r
2314     }\r
2315 \r
2316 \r
2317     else if (strCommand == "submitorder")\r
2318     {\r
2319         uint256 hashReply;\r
2320         CWalletTx wtxNew;\r
2321         vRecv >> hashReply >> wtxNew;\r
2322         wtxNew.fFromMe = false;\r
2323 \r
2324         // Broadcast\r
2325         if (!wtxNew.AcceptWalletTransaction())\r
2326         {\r
2327             pfrom->PushMessage("reply", hashReply, (int)1);\r
2328             return error("submitorder AcceptWalletTransaction() failed, returning error 1");\r
2329         }\r
2330         wtxNew.fTimeReceivedIsTxTime = true;\r
2331         AddToWallet(wtxNew);\r
2332         wtxNew.RelayWalletTransaction();\r
2333         mapReuseKey.erase(pfrom->addr.ip);\r
2334 \r
2335         // Send back confirmation\r
2336         pfrom->PushMessage("reply", hashReply, (int)0);\r
2337     }\r
2338 \r
2339 \r
2340     else if (strCommand == "reply")\r
2341     {\r
2342         uint256 hashReply;\r
2343         vRecv >> hashReply;\r
2344 \r
2345         CRequestTracker tracker;\r
2346         CRITICAL_BLOCK(pfrom->cs_mapRequests)\r
2347         {\r
2348             map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);\r
2349             if (mi != pfrom->mapRequests.end())\r
2350             {\r
2351                 tracker = (*mi).second;\r
2352                 pfrom->mapRequests.erase(mi);\r
2353             }\r
2354         }\r
2355         if (!tracker.IsNull())\r
2356             tracker.fn(tracker.param1, vRecv);\r
2357     }\r
2358 \r
2359 \r
2360     else if (strCommand == "ping")\r
2361     {\r
2362     }\r
2363 \r
2364 \r
2365     else\r
2366     {\r
2367         // Ignore unknown commands for extensibility\r
2368     }\r
2369 \r
2370 \r
2371     // Update the last seen time for this node's address\r
2372     if (pfrom->fNetworkNode)\r
2373         if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")\r
2374             AddressCurrentlyConnected(pfrom->addr);\r
2375 \r
2376 \r
2377     return true;\r
2378 }\r
2379 \r
2380 \r
2381 \r
2382 \r
2383 \r
2384 \r
2385 \r
2386 \r
2387 \r
2388 bool SendMessages(CNode* pto, bool fSendTrickle)\r
2389 {\r
2390     CRITICAL_BLOCK(cs_main)\r
2391     {\r
2392         // Don't send anything until we get their version message\r
2393         if (pto->nVersion == 0)\r
2394             return true;\r
2395 \r
2396         // Keep-alive ping\r
2397         if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty())\r
2398             pto->PushMessage("ping");\r
2399 \r
2400         // Address refresh broadcast\r
2401         static int64 nLastRebroadcast;\r
2402         if (GetTime() - nLastRebroadcast > 24 * 60 * 60) // every 24 hours\r
2403         {\r
2404             nLastRebroadcast = GetTime();\r
2405             CRITICAL_BLOCK(cs_vNodes)\r
2406             {\r
2407                 foreach(CNode* pnode, vNodes)\r
2408                 {\r
2409                     // Periodically clear setAddrKnown to allow refresh broadcasts\r
2410                     pnode->setAddrKnown.clear();\r
2411 \r
2412                     // Rebroadcast our address\r
2413                     if (addrLocalHost.IsRoutable() && !fUseProxy)\r
2414                         pnode->PushAddress(addrLocalHost);\r
2415                 }\r
2416             }\r
2417         }\r
2418 \r
2419         // Resend wallet transactions that haven't gotten in a block yet\r
2420         ResendWalletTransactions();\r
2421 \r
2422 \r
2423         //\r
2424         // Message: addr\r
2425         //\r
2426         if (fSendTrickle)\r
2427         {\r
2428             vector<CAddress> vAddr;\r
2429             vAddr.reserve(pto->vAddrToSend.size());\r
2430             foreach(const CAddress& addr, pto->vAddrToSend)\r
2431             {\r
2432                 // returns true if wasn't already contained in the set\r
2433                 if (pto->setAddrKnown.insert(addr).second)\r
2434                 {\r
2435                     vAddr.push_back(addr);\r
2436                     // receiver rejects addr messages larger than 1000\r
2437                     if (vAddr.size() >= 1000)\r
2438                     {\r
2439                         pto->PushMessage("addr", vAddr);\r
2440                         vAddr.clear();\r
2441                     }\r
2442                 }\r
2443             }\r
2444             pto->vAddrToSend.clear();\r
2445             if (!vAddr.empty())\r
2446                 pto->PushMessage("addr", vAddr);\r
2447         }\r
2448 \r
2449 \r
2450         //\r
2451         // Message: inventory\r
2452         //\r
2453         vector<CInv> vInv;\r
2454         vector<CInv> vInvWait;\r
2455         CRITICAL_BLOCK(pto->cs_inventory)\r
2456         {\r
2457             vInv.reserve(pto->vInventoryToSend.size());\r
2458             vInvWait.reserve(pto->vInventoryToSend.size());\r
2459             foreach(const CInv& inv, pto->vInventoryToSend)\r
2460             {\r
2461                 if (pto->setInventoryKnown.count(inv))\r
2462                     continue;\r
2463 \r
2464                 // trickle out tx inv to protect privacy\r
2465                 if (inv.type == MSG_TX && !fSendTrickle)\r
2466                 {\r
2467                     // 1/4 of tx invs blast to all immediately\r
2468                     static uint256 hashSalt;\r
2469                     if (hashSalt == 0)\r
2470                         RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));\r
2471                     uint256 hashRand = inv.hash ^ hashSalt;\r
2472                     hashRand = Hash(BEGIN(hashRand), END(hashRand));\r
2473                     bool fTrickleWait = ((hashRand & 3) != 0);\r
2474 \r
2475                     // always trickle our own transactions\r
2476                     if (!fTrickleWait)\r
2477                     {\r
2478                         TRY_CRITICAL_BLOCK(cs_mapWallet)\r
2479                         {\r
2480                             map<uint256, CWalletTx>::iterator mi = mapWallet.find(inv.hash);\r
2481                             if (mi != mapWallet.end())\r
2482                             {\r
2483                                 CWalletTx& wtx = (*mi).second;\r
2484                                 if (wtx.fFromMe)\r
2485                                     fTrickleWait = true;\r
2486                             }\r
2487                         }\r
2488                     }\r
2489 \r
2490                     if (fTrickleWait)\r
2491                     {\r
2492                         vInvWait.push_back(inv);\r
2493                         continue;\r
2494                     }\r
2495                 }\r
2496 \r
2497                 // returns true if wasn't already contained in the set\r
2498                 if (pto->setInventoryKnown.insert(inv).second)\r
2499                 {\r
2500                     vInv.push_back(inv);\r
2501                     if (vInv.size() >= 1000)\r
2502                     {\r
2503                         pto->PushMessage("inv", vInv);\r
2504                         vInv.clear();\r
2505                     }\r
2506                 }\r
2507             }\r
2508             pto->vInventoryToSend = vInvWait;\r
2509         }\r
2510         if (!vInv.empty())\r
2511             pto->PushMessage("inv", vInv);\r
2512 \r
2513 \r
2514         //\r
2515         // Message: getdata\r
2516         //\r
2517         vector<CInv> vGetData;\r
2518         int64 nNow = GetTime() * 1000000;\r
2519         CTxDB txdb("r");\r
2520         while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)\r
2521         {\r
2522             const CInv& inv = (*pto->mapAskFor.begin()).second;\r
2523             if (!AlreadyHave(txdb, inv))\r
2524             {\r
2525                 printf("sending getdata: %s\n", inv.ToString().c_str());\r
2526                 vGetData.push_back(inv);\r
2527                 if (vGetData.size() >= 1000)\r
2528                 {\r
2529                     pto->PushMessage("getdata", vGetData);\r
2530                     vGetData.clear();\r
2531                 }\r
2532             }\r
2533             pto->mapAskFor.erase(pto->mapAskFor.begin());\r
2534         }\r
2535         if (!vGetData.empty())\r
2536             pto->PushMessage("getdata", vGetData);\r
2537 \r
2538     }\r
2539     return true;\r
2540 }\r
2541 \r
2542 \r
2543 \r
2544 \r
2545 \r
2546 \r
2547 \r
2548 \r
2549 \r
2550 \r
2551 \r
2552 \r
2553 \r
2554 \r
2555 //////////////////////////////////////////////////////////////////////////////\r
2556 //\r
2557 // BitcoinMiner\r
2558 //\r
2559 \r
2560 void GenerateBitcoins(bool fGenerate)\r
2561 {\r
2562     if (fGenerateBitcoins != fGenerate)\r
2563     {\r
2564         fGenerateBitcoins = fGenerate;\r
2565         CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);\r
2566         MainFrameRepaint();\r
2567     }\r
2568     if (fGenerateBitcoins)\r
2569     {\r
2570         int nProcessors = boost::thread::hardware_concurrency();\r
2571         printf("%d processors\n", nProcessors);\r
2572         if (nProcessors < 1)\r
2573             nProcessors = 1;\r
2574         if (fLimitProcessors && nProcessors > nLimitProcessors)\r
2575             nProcessors = nLimitProcessors;\r
2576         int nAddThreads = nProcessors - vnThreadsRunning[3];\r
2577         printf("Starting %d BitcoinMiner threads\n", nAddThreads);\r
2578         for (int i = 0; i < nAddThreads; i++)\r
2579         {\r
2580             if (!CreateThread(ThreadBitcoinMiner, NULL))\r
2581                 printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");\r
2582             Sleep(10);\r
2583         }\r
2584     }\r
2585 }\r
2586 \r
2587 void ThreadBitcoinMiner(void* parg)\r
2588 {\r
2589     try\r
2590     {\r
2591         vnThreadsRunning[3]++;\r
2592         BitcoinMiner();\r
2593         vnThreadsRunning[3]--;\r
2594     }\r
2595     catch (std::exception& e) {\r
2596         vnThreadsRunning[3]--;\r
2597         PrintException(&e, "ThreadBitcoinMiner()");\r
2598     } catch (...) {\r
2599         vnThreadsRunning[3]--;\r
2600         PrintException(NULL, "ThreadBitcoinMiner()");\r
2601     }\r
2602     UIThreadCall(bind(CalledSetStatusBar, "", 0));\r
2603     nHPSTimerStart = 0;\r
2604     if (vnThreadsRunning[3] == 0)\r
2605         dHashesPerSec = 0;\r
2606     printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);\r
2607 }\r
2608 \r
2609 int FormatHashBlocks(void* pbuffer, unsigned int len)\r
2610 {\r
2611     unsigned char* pdata = (unsigned char*)pbuffer;\r
2612     unsigned int blocks = 1 + ((len + 8) / 64);\r
2613     unsigned char* pend = pdata + 64 * blocks;\r
2614     memset(pdata + len, 0, 64 * blocks - len);\r
2615     pdata[len] = 0x80;\r
2616     unsigned int bits = len * 8;\r
2617     pend[-1] = (bits >> 0) & 0xff;\r
2618     pend[-2] = (bits >> 8) & 0xff;\r
2619     pend[-3] = (bits >> 16) & 0xff;\r
2620     pend[-4] = (bits >> 24) & 0xff;\r
2621     return blocks;\r
2622 }\r
2623 \r
2624 using CryptoPP::ByteReverse;\r
2625 \r
2626 static const unsigned int pSHA256InitState[8] =\r
2627 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};\r
2628 \r
2629 inline void SHA256Transform(void* pstate, void* pinput, const void* pinit)\r
2630 {\r
2631     memcpy(pstate, pinit, 32);\r
2632     CryptoPP::SHA256::Transform((CryptoPP::word32*)pstate, (CryptoPP::word32*)pinput);\r
2633 }\r
2634 \r
2635 static const int NPAR = 32;\r
2636 extern void Double_BlockSHA256(const void* pin, void* pout, const void* pinit, unsigned int hash[8][NPAR], const void* init2);\r
2637 \r
2638 \r
2639 \r
2640 \r
2641 void BitcoinMiner()\r
2642 {\r
2643     printf("BitcoinMiner started\n");\r
2644     SetThreadPriority(THREAD_PRIORITY_LOWEST);\r
2645 \r
2646     CKey key;\r
2647     key.MakeNewKey();\r
2648     CBigNum bnExtraNonce = 0;\r
2649     while (fGenerateBitcoins)\r
2650     {\r
2651         Sleep(50);\r
2652         if (fShutdown)\r
2653             return;\r
2654         while (vNodes.empty() || IsInitialBlockDownload())\r
2655         {\r
2656             Sleep(1000);\r
2657             if (fShutdown)\r
2658                 return;\r
2659             if (!fGenerateBitcoins)\r
2660                 return;\r
2661         }\r
2662 \r
2663         unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;\r
2664         CBlockIndex* pindexPrev = pindexBest;\r
2665         unsigned int nBits = GetNextWorkRequired(pindexPrev);\r
2666 \r
2667 \r
2668         //\r
2669         // Create coinbase tx\r
2670         //\r
2671         CTransaction txNew;\r
2672         txNew.vin.resize(1);\r
2673         txNew.vin[0].prevout.SetNull();\r
2674         txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;\r
2675         txNew.vout.resize(1);\r
2676         txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;\r
2677 \r
2678 \r
2679         //\r
2680         // Create new block\r
2681         //\r
2682         auto_ptr<CBlock> pblock(new CBlock());\r
2683         if (!pblock.get())\r
2684             return;\r
2685 \r
2686         // Add our coinbase tx as first transaction\r
2687         pblock->vtx.push_back(txNew);\r
2688 \r
2689         // Collect the latest transactions into the block\r
2690         int64 nFees = 0;\r
2691         CRITICAL_BLOCK(cs_main)\r
2692         CRITICAL_BLOCK(cs_mapTransactions)\r
2693         {\r
2694             CTxDB txdb("r");\r
2695             map<uint256, CTxIndex> mapTestPool;\r
2696             vector<char> vfAlreadyAdded(mapTransactions.size());\r
2697             bool fFoundSomething = true;\r
2698             unsigned int nBlockSize = 0;\r
2699             while (fFoundSomething && nBlockSize < MAX_SIZE/2)\r
2700             {\r
2701                 fFoundSomething = false;\r
2702                 unsigned int n = 0;\r
2703                 for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)\r
2704                 {\r
2705                     if (vfAlreadyAdded[n])\r
2706                         continue;\r
2707                     CTransaction& tx = (*mi).second;\r
2708                     if (tx.IsCoinBase() || !tx.IsFinal())\r
2709                         continue;\r
2710                     unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);\r
2711                     if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE - 10000)\r
2712                         continue;\r
2713 \r
2714                     // Transaction fee based on block size\r
2715                     int64 nMinFee = tx.GetMinFee(nBlockSize);\r
2716 \r
2717                     map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);\r
2718                     if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee))\r
2719                         continue;\r
2720                     swap(mapTestPool, mapTestPoolTmp);\r
2721 \r
2722                     pblock->vtx.push_back(tx);\r
2723                     nBlockSize += nTxSize;\r
2724                     vfAlreadyAdded[n] = true;\r
2725                     fFoundSomething = true;\r
2726                 }\r
2727             }\r
2728         }\r
2729         pblock->nBits = nBits;\r
2730         pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(pindexPrev->nHeight+1, nFees);\r
2731         printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());\r
2732 \r
2733 \r
2734         //\r
2735         // Prebuild hash buffer\r
2736         //\r
2737         struct tmpworkspace\r
2738         {\r
2739             struct unnamed2\r
2740             {\r
2741                 int nVersion;\r
2742                 uint256 hashPrevBlock;\r
2743                 uint256 hashMerkleRoot;\r
2744                 unsigned int nTime;\r
2745                 unsigned int nBits;\r
2746                 unsigned int nNonce;\r
2747             }\r
2748             block;\r
2749             unsigned char pchPadding0[64];\r
2750             uint256 hash1;\r
2751             unsigned char pchPadding1[64];\r
2752         };\r
2753         char tmpbuf[sizeof(tmpworkspace)+16];\r
2754         tmpworkspace& tmp = *(tmpworkspace*)alignup<16>(tmpbuf);\r
2755 \r
2756         tmp.block.nVersion       = pblock->nVersion;\r
2757         tmp.block.hashPrevBlock  = pblock->hashPrevBlock  = (pindexPrev ? pindexPrev->GetBlockHash() : 0);\r
2758         tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();\r
2759         tmp.block.nTime          = pblock->nTime          = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());\r
2760         tmp.block.nBits          = pblock->nBits          = nBits;\r
2761         tmp.block.nNonce         = pblock->nNonce         = 0;\r
2762 \r
2763         unsigned int nBlocks0 = FormatHashBlocks(&tmp.block, sizeof(tmp.block));\r
2764         unsigned int nBlocks1 = FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));\r
2765 \r
2766         // Byte swap all the input buffer\r
2767         for (int i = 0; i < sizeof(tmp)/4; i++)\r
2768             ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);\r
2769 \r
2770         // Precalc the first half of the first hash, which stays constant\r
2771         uint256 midstatebuf[2];\r
2772         uint256& midstate = *alignup<16>(midstatebuf);\r
2773         SHA256Transform(&midstate, &tmp.block, pSHA256InitState);\r
2774 \r
2775 \r
2776         //\r
2777         // Search\r
2778         //\r
2779         bool f4WaySSE2 = mapArgs.count("-4way");\r
2780         int64 nStart = GetTime();\r
2781         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();\r
2782         uint256 hashbuf[2];\r
2783         uint256& hash = *alignup<16>(hashbuf);\r
2784         loop\r
2785         {\r
2786 #ifdef FOURWAYSSE2\r
2787             if (f4WaySSE2)\r
2788             {\r
2789                 // tcatm's 4-way SSE2 SHA-256\r
2790                 tmp.block.nNonce += NPAR;\r
2791                 unsigned int thashbuf[9][NPAR];\r
2792                 unsigned int (&thash)[9][NPAR] = *alignup<16>(&thashbuf);\r
2793                 Double_BlockSHA256((char*)&tmp.block + 64, &tmp.hash1, &midstate, thash, pSHA256InitState);\r
2794                 ((unsigned short*)&hash)[14] = 0xffff;\r
2795                 for (int j = 0; j < NPAR; j++)\r
2796                 {\r
2797                     if (thash[7][j] == 0)\r
2798                     {\r
2799                         for (int i = 0; i < sizeof(hash)/4; i++)\r
2800                             ((unsigned int*)&hash)[i] = thash[i][j];\r
2801                         pblock->nNonce = ByteReverse(tmp.block.nNonce + j);\r
2802                     }\r
2803                 }\r
2804             }\r
2805             else\r
2806 #endif\r
2807             {\r
2808                 // Crypto++ SHA-256\r
2809                 tmp.block.nNonce++;\r
2810                 SHA256Transform(&tmp.hash1, (char*)&tmp.block + 64, &midstate);\r
2811                 SHA256Transform(&hash, &tmp.hash1, pSHA256InitState);\r
2812             }\r
2813 \r
2814             if (((unsigned short*)&hash)[14] == 0)\r
2815             {\r
2816                 // Byte swap the result after preliminary check\r
2817                 for (int i = 0; i < sizeof(hash)/4; i++)\r
2818                     ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);\r
2819 \r
2820                 if (hash <= hashTarget)\r
2821                 {\r
2822 #ifdef FOURWAYSSE2\r
2823                     if (!f4WaySSE2)\r
2824 #endif\r
2825                         pblock->nNonce = ByteReverse(tmp.block.nNonce);\r
2826                     assert(hash == pblock->GetHash());\r
2827 \r
2828                         //// debug print\r
2829                         printf("BitcoinMiner:\n");\r
2830                         printf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());\r
2831                         pblock->print();\r
2832                         printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());\r
2833                         printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());\r
2834 \r
2835                     SetThreadPriority(THREAD_PRIORITY_NORMAL);\r
2836                     CRITICAL_BLOCK(cs_main)\r
2837                     {\r
2838                         if (pindexPrev == pindexBest)\r
2839                         {\r
2840                             // Save key\r
2841                             if (!AddKey(key))\r
2842                                 return;\r
2843                             key.MakeNewKey();\r
2844 \r
2845                             // Track how many getdata requests this block gets\r
2846                             CRITICAL_BLOCK(cs_mapRequestCount)\r
2847                                 mapRequestCount[pblock->GetHash()] = 0;\r
2848 \r
2849                             // Process this block the same as if we had received it from another node\r
2850                             if (!ProcessBlock(NULL, pblock.release()))\r
2851                                 printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");\r
2852                         }\r
2853                     }\r
2854                     SetThreadPriority(THREAD_PRIORITY_LOWEST);\r
2855 \r
2856                     Sleep(500);\r
2857                     break;\r
2858                 }\r
2859             }\r
2860 \r
2861             // Update nTime every few seconds\r
2862             const unsigned int nMask = 0xffff;\r
2863             const int nHashesPerCycle = (nMask+1);\r
2864             if ((tmp.block.nNonce & nMask) == 0)\r
2865             {\r
2866                 // Meter hashes/sec\r
2867                 static int nCycleCounter;\r
2868                 if (nHPSTimerStart == 0)\r
2869                 {\r
2870                     nHPSTimerStart = GetTimeMillis();\r
2871                     nCycleCounter = 0;\r
2872                 }\r
2873                 else\r
2874                     nCycleCounter++;\r
2875                 if (GetTimeMillis() - nHPSTimerStart > 4000)\r
2876                 {\r
2877                     static CCriticalSection cs;\r
2878                     CRITICAL_BLOCK(cs)\r
2879                     {\r
2880                         if (GetTimeMillis() - nHPSTimerStart > 4000)\r
2881                         {\r
2882                             dHashesPerSec = 1000.0 * nHashesPerCycle * nCycleCounter / (GetTimeMillis() - nHPSTimerStart);\r
2883                             nHPSTimerStart = GetTimeMillis();\r
2884                             nCycleCounter = 0;\r
2885                             string strStatus = strprintf("    %.0f khash/s", dHashesPerSec/1000.0);\r
2886                             UIThreadCall(bind(CalledSetStatusBar, strStatus, 0));\r
2887                             static int64 nLogTime;\r
2888                             if (GetTime() - nLogTime > 30 * 60)\r
2889                             {\r
2890                                 nLogTime = GetTime();\r
2891                                 printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());\r
2892                                 printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[3], dHashesPerSec/1000.0);\r
2893                             }\r
2894                         }\r
2895                     }\r
2896                 }\r
2897 \r
2898                 // Check for stop or if block needs to be rebuilt\r
2899                 if (fShutdown)\r
2900                     return;\r
2901                 if (!fGenerateBitcoins)\r
2902                     return;\r
2903                 if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)\r
2904                     return;\r
2905                 if (vNodes.empty())\r
2906                     break;\r
2907                 if (tmp.block.nNonce == 0)\r
2908                     break;\r
2909                 if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)\r
2910                     break;\r
2911                 if (pindexPrev != pindexBest)\r
2912                     break;\r
2913 \r
2914                 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());\r
2915                 tmp.block.nTime = ByteReverse(pblock->nTime);\r
2916             }\r
2917         }\r
2918     }\r
2919 }\r
2920 \r
2921 \r
2922 \r
2923 \r
2924 \r
2925 \r
2926 \r
2927 \r
2928 \r
2929 \r
2930 \r
2931 \r
2932 \r
2933 \r
2934 \r
2935 \r
2936 \r
2937 \r
2938 //////////////////////////////////////////////////////////////////////////////\r
2939 //\r
2940 // Actions\r
2941 //\r
2942 \r
2943 \r
2944 int64 GetBalance()\r
2945 {\r
2946     int64 nStart = GetTimeMillis();\r
2947 \r
2948     int64 nTotal = 0;\r
2949     CRITICAL_BLOCK(cs_mapWallet)\r
2950     {\r
2951         for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)\r
2952         {\r
2953             CWalletTx* pcoin = &(*it).second;\r
2954             if (!pcoin->IsFinal() || pcoin->fSpent)\r
2955                 continue;\r
2956             nTotal += pcoin->GetCredit(true);\r
2957         }\r
2958     }\r
2959 \r
2960     //printf("GetBalance() %"PRI64d"ms\n", GetTimeMillis() - nStart);\r
2961     return nTotal;\r
2962 }\r
2963 \r
2964 \r
2965 int GetRandInt(int nMax)\r
2966 {\r
2967     return GetRand(nMax);\r
2968 }\r
2969 \r
2970 bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)\r
2971 {\r
2972     setCoinsRet.clear();\r
2973 \r
2974     // List of values less than target\r
2975     int64 nLowestLarger = INT64_MAX;\r
2976     CWalletTx* pcoinLowestLarger = NULL;\r
2977     vector<pair<int64, CWalletTx*> > vValue;\r
2978     int64 nTotalLower = 0;\r
2979 \r
2980     CRITICAL_BLOCK(cs_mapWallet)\r
2981     {\r
2982        vector<CWalletTx*> vCoins;\r
2983        vCoins.reserve(mapWallet.size());\r
2984        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)\r
2985            vCoins.push_back(&(*it).second);\r
2986        random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);\r
2987 \r
2988        foreach(CWalletTx* pcoin, vCoins)\r
2989        {\r
2990             if (!pcoin->IsFinal() || pcoin->fSpent)\r
2991                 continue;\r
2992             int64 n = pcoin->GetCredit();\r
2993             if (n <= 0)\r
2994                 continue;\r
2995             if (n < nTargetValue)\r
2996             {\r
2997                 vValue.push_back(make_pair(n, pcoin));\r
2998                 nTotalLower += n;\r
2999             }\r
3000             else if (n == nTargetValue)\r
3001             {\r
3002                 setCoinsRet.insert(pcoin);\r
3003                 return true;\r
3004             }\r
3005             else if (n < nLowestLarger)\r
3006             {\r
3007                 nLowestLarger = n;\r
3008                 pcoinLowestLarger = pcoin;\r
3009             }\r
3010         }\r
3011     }\r
3012 \r
3013     if (nTotalLower < nTargetValue)\r
3014     {\r
3015         if (pcoinLowestLarger == NULL)\r
3016             return false;\r
3017         setCoinsRet.insert(pcoinLowestLarger);\r
3018         return true;\r
3019     }\r
3020 \r
3021     // Solve subset sum by stochastic approximation\r
3022     sort(vValue.rbegin(), vValue.rend());\r
3023     vector<char> vfIncluded;\r
3024     vector<char> vfBest(vValue.size(), true);\r
3025     int64 nBest = nTotalLower;\r
3026 \r
3027     for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)\r
3028     {\r
3029         vfIncluded.assign(vValue.size(), false);\r
3030         int64 nTotal = 0;\r
3031         bool fReachedTarget = false;\r
3032         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)\r
3033         {\r
3034             for (int i = 0; i < vValue.size(); i++)\r
3035             {\r
3036                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])\r
3037                 {\r
3038                     nTotal += vValue[i].first;\r
3039                     vfIncluded[i] = true;\r
3040                     if (nTotal >= nTargetValue)\r
3041                     {\r
3042                         fReachedTarget = true;\r
3043                         if (nTotal < nBest)\r
3044                         {\r
3045                             nBest = nTotal;\r
3046                             vfBest = vfIncluded;\r
3047                         }\r
3048                         nTotal -= vValue[i].first;\r
3049                         vfIncluded[i] = false;\r
3050                     }\r
3051                 }\r
3052             }\r
3053         }\r
3054     }\r
3055 \r
3056     // If the next larger is still closer, return it\r
3057     if (pcoinLowestLarger && nLowestLarger - nTargetValue <= nBest - nTargetValue)\r
3058         setCoinsRet.insert(pcoinLowestLarger);\r
3059     else\r
3060     {\r
3061         for (int i = 0; i < vValue.size(); i++)\r
3062             if (vfBest[i])\r
3063                 setCoinsRet.insert(vValue[i].second);\r
3064 \r
3065         //// debug print\r
3066         printf("SelectCoins() best subset: ");\r
3067         for (int i = 0; i < vValue.size(); i++)\r
3068             if (vfBest[i])\r
3069                 printf("%s ", FormatMoney(vValue[i].first).c_str());\r
3070         printf("total %s\n", FormatMoney(nBest).c_str());\r
3071     }\r
3072 \r
3073     return true;\r
3074 }\r
3075 \r
3076 \r
3077 \r
3078 \r
3079 bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet)\r
3080 {\r
3081     nFeeRequiredRet = 0;\r
3082     CRITICAL_BLOCK(cs_main)\r
3083     {\r
3084         // txdb must be opened before the mapWallet lock\r
3085         CTxDB txdb("r");\r
3086         CRITICAL_BLOCK(cs_mapWallet)\r
3087         {\r
3088             int64 nFee = nTransactionFee;\r
3089             loop\r
3090             {\r
3091                 wtxNew.vin.clear();\r
3092                 wtxNew.vout.clear();\r
3093                 wtxNew.fFromMe = true;\r
3094                 if (nValue < 0)\r
3095                     return false;\r
3096                 int64 nValueOut = nValue;\r
3097                 int64 nTotalValue = nValue + nFee;\r
3098 \r
3099                 // Choose coins to use\r
3100                 set<CWalletTx*> setCoins;\r
3101                 if (!SelectCoins(nTotalValue, setCoins))\r
3102                     return false;\r
3103                 int64 nValueIn = 0;\r
3104                 foreach(CWalletTx* pcoin, setCoins)\r
3105                     nValueIn += pcoin->GetCredit();\r
3106 \r
3107                 // Fill a vout to the payee\r
3108                 bool fChangeFirst = GetRand(2);\r
3109                 if (!fChangeFirst)\r
3110                     wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));\r
3111 \r
3112                 // Fill a vout back to self with any change\r
3113                 if (nValueIn > nTotalValue)\r
3114                 {\r
3115                     // Note: We use a new key here to keep it from being obvious which side is the change.\r
3116                     //  The drawback is that by not reusing a previous key, the change may be lost if a\r
3117                     //  backup is restored, if the backup doesn't have the new private key for the change.\r
3118                     //  If we reused the old key, it would be possible to add code to look for and\r
3119                     //  rediscover unknown transactions that were written with keys of ours to recover\r
3120                     //  post-backup change.\r
3121 \r
3122                     // New private key\r
3123                     if (keyRet.IsNull())\r
3124                         keyRet.MakeNewKey();\r
3125 \r
3126                     // Fill a vout to ourself, using same address type as the payment\r
3127                     CScript scriptChange;\r
3128                     if (scriptPubKey.GetBitcoinAddressHash160() != 0)\r
3129                         scriptChange.SetBitcoinAddress(keyRet.GetPubKey());\r
3130                     else\r
3131                         scriptChange << keyRet.GetPubKey() << OP_CHECKSIG;\r
3132                     wtxNew.vout.push_back(CTxOut(nValueIn - nTotalValue, scriptChange));\r
3133                 }\r
3134 \r
3135                 // Fill a vout to the payee\r
3136                 if (fChangeFirst)\r
3137                     wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));\r
3138 \r
3139                 // Fill vin\r
3140                 foreach(CWalletTx* pcoin, setCoins)\r
3141                     for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)\r
3142                         if (pcoin->vout[nOut].IsMine())\r
3143                             wtxNew.vin.push_back(CTxIn(pcoin->GetHash(), nOut));\r
3144 \r
3145                 // Sign\r
3146                 int nIn = 0;\r
3147                 foreach(CWalletTx* pcoin, setCoins)\r
3148                     for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)\r
3149                         if (pcoin->vout[nOut].IsMine())\r
3150                             if (!SignSignature(*pcoin, wtxNew, nIn++))\r
3151                                 return false;\r
3152 \r
3153                 // Check that enough fee is included\r
3154                 if (nFee < wtxNew.GetMinFee())\r
3155                 {\r
3156                     nFee = nFeeRequiredRet = wtxNew.GetMinFee();\r
3157                     continue;\r
3158                 }\r
3159 \r
3160                 // Fill vtxPrev by copying from previous transactions vtxPrev\r
3161                 wtxNew.AddSupportingTransactions(txdb);\r
3162                 wtxNew.fTimeReceivedIsTxTime = true;\r
3163 \r
3164                 break;\r
3165             }\r
3166         }\r
3167     }\r
3168     return true;\r
3169 }\r
3170 \r
3171 // Call after CreateTransaction unless you want to abort\r
3172 bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)\r
3173 {\r
3174     CRITICAL_BLOCK(cs_main)\r
3175     {\r
3176         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());\r
3177         CRITICAL_BLOCK(cs_mapWallet)\r
3178         {\r
3179             // This is only to keep the database open to defeat the auto-flush for the\r
3180             // duration of this scope.  This is the only place where this optimization\r
3181             // maybe makes sense; please don't do it anywhere else.\r
3182             CWalletDB walletdb("r");\r
3183 \r
3184             // Add the change's private key to wallet\r
3185             if (!key.IsNull() && !AddKey(key))\r
3186                 throw runtime_error("CommitTransaction() : AddKey failed\n");\r
3187 \r
3188             // Add tx to wallet, because if it has change it's also ours,\r
3189             // otherwise just for transaction history.\r
3190             AddToWallet(wtxNew);\r
3191 \r
3192             // Mark old coins as spent\r
3193             set<CWalletTx*> setCoins;\r
3194             foreach(const CTxIn& txin, wtxNew.vin)\r
3195                 setCoins.insert(&mapWallet[txin.prevout.hash]);\r
3196             foreach(CWalletTx* pcoin, setCoins)\r
3197             {\r
3198                 pcoin->fSpent = true;\r
3199                 pcoin->WriteToDisk();\r
3200                 vWalletUpdated.push_back(pcoin->GetHash());\r
3201             }\r
3202         }\r
3203 \r
3204         // Track how many getdata requests our transaction gets\r
3205         CRITICAL_BLOCK(cs_mapRequestCount)\r
3206             mapRequestCount[wtxNew.GetHash()] = 0;\r
3207 \r
3208         // Broadcast\r
3209         if (!wtxNew.AcceptTransaction())\r
3210         {\r
3211             // This must not fail. The transaction has already been signed and recorded.\r
3212             printf("CommitTransaction() : Error: Transaction not valid");\r
3213             return false;\r
3214         }\r
3215         wtxNew.RelayWalletTransaction();\r
3216     }\r
3217     MainFrameRepaint();\r
3218     return true;\r
3219 }\r
3220 \r
3221 \r
3222 \r
3223 \r
3224 string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)\r
3225 {\r
3226     CRITICAL_BLOCK(cs_main)\r
3227     {\r
3228         CKey key;\r
3229         int64 nFeeRequired;\r
3230         if (!CreateTransaction(scriptPubKey, nValue, wtxNew, key, nFeeRequired))\r
3231         {\r
3232             string strError;\r
3233             if (nValue + nFeeRequired > GetBalance())\r
3234                 strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s  "), FormatMoney(nFeeRequired).c_str());\r
3235             else\r
3236                 strError = _("Error: Transaction creation failed  ");\r
3237             printf("SendMoney() : %s", strError.c_str());\r
3238             return strError;\r
3239         }\r
3240 \r
3241         if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))\r
3242             return "ABORTED";\r
3243 \r
3244         if (!CommitTransaction(wtxNew, key))\r
3245             return _("Error: The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");\r
3246     }\r
3247     MainFrameRepaint();\r
3248     return "";\r
3249 }\r
3250 \r
3251 \r
3252 \r
3253 string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)\r
3254 {\r
3255     // Check amount\r
3256     if (nValue <= 0)\r
3257         return _("Invalid amount");\r
3258     if (nValue + nTransactionFee > GetBalance())\r
3259         return _("Insufficient funds");\r
3260 \r
3261     // Parse bitcoin address\r
3262     CScript scriptPubKey;\r
3263     if (!scriptPubKey.SetBitcoinAddress(strAddress))\r
3264         return _("Invalid bitcoin address");\r
3265 \r
3266     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);\r
3267 }\r