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