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