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