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