genesis 1
genesis 2
genesis 3
genesis 4
genesis 5 #include "headers.h"
genesis 6 #include "checkpoints.h"
genesis 7 #include "db.h"
genesis 8 #include "net.h"
genesis 9 #include "init.h"
genesis 10 #include <boost/filesystem.hpp>
genesis 11 #include <boost/filesystem/fstream.hpp>
genesis 12
genesis 13 using namespace std;
genesis 14 using namespace boost;
genesis 15
genesis 16
genesis 17
genesis 18
genesis 19
programmable-vers... 20 int VERSION = DEFAULT_CLIENT_VERSION;
programmable-vers... 21
genesis 22 CCriticalSection cs_setpwalletRegistered;
genesis 23 set<CWallet*> setpwalletRegistered;
genesis 24
genesis 25 CCriticalSection cs_main;
genesis 26
genesis 27 static map<uint256, CTransaction> mapTransactions;
genesis 28 CCriticalSection cs_mapTransactions;
genesis 29 unsigned int nTransactionsUpdated = 0;
genesis 30 map<COutPoint, CInPoint> mapNextTx;
genesis 31
genesis 32 map<uint256, CBlockIndex*> mapBlockIndex;
genesis 33 uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
genesis 34 static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
genesis 35 CBlockIndex* pindexGenesisBlock = NULL;
genesis 36 int nBestHeight = -1;
genesis 37 CBigNum bnBestChainWork = 0;
genesis 38 CBigNum bnBestInvalidWork = 0;
genesis 39 uint256 hashBestChain = 0;
genesis 40 CBlockIndex* pindexBest = NULL;
genesis 41 int64 nTimeBestReceived = 0;
genesis 42
genesis 43 CMedianFilter<int> cPeerBlockCounts(5, 0);
genesis 44
genesis 45
genesis 46
genesis 47 double dHashesPerSec;
genesis 48 int64 nHPSTimerStart;
genesis 49
genesis 50
genesis 51 int fGenerateBitcoins = false;
genesis 52 int64 nTransactionFee = 0;
genesis 53 int fLimitProcessors = false;
genesis 54 int nLimitProcessors = 1;
genesis 55 int fMinimizeToTray = true;
genesis 56 int fMinimizeOnClose = true;
genesis 57
genesis 58
genesis 59
genesis 60
genesis 61
genesis 62
genesis 63
genesis 64
genesis 65
genesis 66
genesis 67 void RegisterWallet(CWallet* pwalletIn)
genesis 68 {
genesis 69 CRITICAL_BLOCK(cs_setpwalletRegistered)
genesis 70 {
genesis 71 setpwalletRegistered.insert(pwalletIn);
genesis 72 }
genesis 73 }
genesis 74
genesis 75 void UnregisterWallet(CWallet* pwalletIn)
genesis 76 {
genesis 77 CRITICAL_BLOCK(cs_setpwalletRegistered)
genesis 78 {
genesis 79 setpwalletRegistered.erase(pwalletIn);
genesis 80 }
genesis 81 }
genesis 82
genesis 83
genesis 84 bool static IsFromMe(CTransaction& tx)
genesis 85 {
genesis 86 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 87 if (pwallet->IsFromMe(tx))
genesis 88 return true;
genesis 89 return false;
genesis 90 }
genesis 91
genesis 92
genesis 93 bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
genesis 94 {
genesis 95 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 96 if (pwallet->GetTransaction(hashTx,wtx))
genesis 97 return true;
genesis 98 return false;
genesis 99 }
genesis 100
genesis 101
genesis 102 void static EraseFromWallets(uint256 hash)
genesis 103 {
genesis 104 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 105 pwallet->EraseFromWallet(hash);
genesis 106 }
genesis 107
genesis 108
genesis 109 void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false)
genesis 110 {
genesis 111 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 112 pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
genesis 113 }
genesis 114
genesis 115
genesis 116 void static SetBestChain(const CBlockLocator& loc)
genesis 117 {
genesis 118 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 119 pwallet->SetBestChain(loc);
genesis 120 }
genesis 121
genesis 122
genesis 123 void static UpdatedTransaction(const uint256& hashTx)
genesis 124 {
genesis 125 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 126 pwallet->UpdatedTransaction(hashTx);
genesis 127 }
genesis 128
genesis 129
genesis 130 void static PrintWallets(const CBlock& block)
genesis 131 {
genesis 132 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 133 pwallet->PrintWallet(block);
genesis 134 }
genesis 135
genesis 136
genesis 137 void static Inventory(const uint256& hash)
genesis 138 {
genesis 139 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 140 pwallet->Inventory(hash);
genesis 141 }
genesis 142
genesis 143
genesis 144 void static ResendWalletTransactions()
genesis 145 {
genesis 146 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
genesis 147 pwallet->ResendWalletTransactions();
genesis 148 }
genesis 149
genesis 150
genesis 151
genesis 152
genesis 153
genesis 154
genesis 155
genesis 156 bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet)
genesis 157 {
genesis 158 SetNull();
genesis 159 if (!txdb.ReadTxIndex(prevout.hash, txindexRet))
genesis 160 return false;
genesis 161 if (!ReadFromDisk(txindexRet.pos))
genesis 162 return false;
genesis 163 if (prevout.n >= vout.size())
genesis 164 {
genesis 165 SetNull();
genesis 166 return false;
genesis 167 }
genesis 168 return true;
genesis 169 }
genesis 170
genesis 171 bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout)
genesis 172 {
genesis 173 CTxIndex txindex;
genesis 174 return ReadFromDisk(txdb, prevout, txindex);
genesis 175 }
genesis 176
genesis 177 bool CTransaction::ReadFromDisk(COutPoint prevout)
genesis 178 {
genesis 179 CTxDB txdb("r");
genesis 180 CTxIndex txindex;
genesis 181 return ReadFromDisk(txdb, prevout, txindex);
genesis 182 }
genesis 183
genesis 184
genesis 185
genesis 186 int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
genesis 187 {
genesis 188 if (fClient)
genesis 189 {
genesis 190 if (hashBlock == 0)
genesis 191 return 0;
genesis 192 }
genesis 193 else
genesis 194 {
genesis 195 CBlock blockTmp;
genesis 196 if (pblock == NULL)
genesis 197 {
genesis 198
genesis 199 CTxIndex txindex;
genesis 200 if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
genesis 201 return 0;
genesis 202 if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))
genesis 203 return 0;
genesis 204 pblock = &blockTmp;
genesis 205 }
genesis 206
genesis 207
genesis 208 hashBlock = pblock->GetHash();
genesis 209
genesis 210
genesis 211 for (nIndex = 0; nIndex < pblock->vtx.size(); nIndex++)
genesis 212 if (pblock->vtx[nIndex] == *(CTransaction*)this)
genesis 213 break;
genesis 214 if (nIndex == pblock->vtx.size())
genesis 215 {
genesis 216 vMerkleBranch.clear();
genesis 217 nIndex = -1;
genesis 218 printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
genesis 219 return 0;
genesis 220 }
genesis 221
genesis 222
genesis 223 vMerkleBranch = pblock->GetMerkleBranch(nIndex);
genesis 224 }
genesis 225
genesis 226
genesis 227 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
genesis 228 if (mi == mapBlockIndex.end())
genesis 229 return 0;
genesis 230 CBlockIndex* pindex = (*mi).second;
genesis 231 if (!pindex || !pindex->IsInMainChain())
genesis 232 return 0;
genesis 233
genesis 234 return pindexBest->nHeight - pindex->nHeight + 1;
genesis 235 }
genesis 236
genesis 237
genesis 238
genesis 239
genesis 240
genesis 241
genesis 242
genesis 243 bool CTransaction::CheckTransaction() const
genesis 244 {
genesis 245
genesis 246 if (vin.empty())
genesis 247 return DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
genesis 248 if (vout.empty())
genesis 249 return DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
genesis 250
genesis 251 if (::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE)
genesis 252 return DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
genesis 253
genesis 254
genesis 255 int64 nValueOut = 0;
genesis 256 BOOST_FOREACH(const CTxOut& txout, vout)
genesis 257 {
genesis 258 if (txout.nValue < 0)
genesis 259 return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue negative"));
genesis 260 if (txout.nValue > MAX_MONEY)
genesis 261 return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
genesis 262 nValueOut += txout.nValue;
genesis 263 if (!MoneyRange(nValueOut))
genesis 264 return DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
genesis 265 }
genesis 266
genesis 267
genesis 268 set<COutPoint> vInOutPoints;
genesis 269 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 270 {
genesis 271 if (vInOutPoints.count(txin.prevout))
genesis 272 return false;
genesis 273 vInOutPoints.insert(txin.prevout);
genesis 274 }
genesis 275
genesis 276 if (IsCoinBase())
genesis 277 {
genesis 278 if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
genesis 279 return DoS(100, error("CTransaction::CheckTransaction() : coinbase script size"));
genesis 280 }
genesis 281 else
genesis 282 {
genesis 283 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 284 if (txin.prevout.IsNull())
genesis 285 return DoS(10, error("CTransaction::CheckTransaction() : prevout is null"));
genesis 286 }
genesis 287
genesis 288 return true;
genesis 289 }
genesis 290
genesis 291 bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
genesis 292 {
genesis 293 if (pfMissingInputs)
genesis 294 *pfMissingInputs = false;
genesis 295
genesis 296 if (!CheckTransaction())
genesis 297 return error("AcceptToMemoryPool() : CheckTransaction failed");
genesis 298
genesis 299
genesis 300 if (IsCoinBase())
genesis 301 return DoS(100, error("AcceptToMemoryPool() : coinbase as individual tx"));
genesis 302
genesis 303
genesis 304 if ((int64)nLockTime > INT_MAX)
genesis 305 return error("AcceptToMemoryPool() : not accepting nLockTime beyond 2038 yet");
genesis 306
genesis 307
genesis 308 unsigned int nSize = ::GetSerializeSize(*this, SER_NETWORK);
genesis 309
genesis 310
genesis 311
genesis 312
genesis 313 if (GetSigOpCount() > nSize / 34 || nSize < 100)
genesis 314 return error("AcceptToMemoryPool() : transaction with out-of-bounds SigOpCount");
genesis 315
asciilifeform_let... 316
asciilifeform_let... 317 if (!IsStandard())
genesis 318 return error("AcceptToMemoryPool() : nonstandard transaction type");
genesis 319
genesis 320
genesis 321 uint256 hash = GetHash();
genesis 322 CRITICAL_BLOCK(cs_mapTransactions)
genesis 323 if (mapTransactions.count(hash))
genesis 324 return false;
genesis 325 if (fCheckInputs)
genesis 326 if (txdb.ContainsTx(hash))
genesis 327 return false;
genesis 328
genesis 329
genesis 330 CTransaction* ptxOld = NULL;
genesis 331 for (int i = 0; i < vin.size(); i++)
genesis 332 {
genesis 333 COutPoint outpoint = vin[i].prevout;
genesis 334 if (mapNextTx.count(outpoint))
genesis 335 {
genesis 336
genesis 337 return false;
genesis 338
genesis 339
genesis 340 if (i != 0)
genesis 341 return false;
genesis 342 ptxOld = mapNextTx[outpoint].ptx;
genesis 343 if (ptxOld->IsFinal())
genesis 344 return false;
genesis 345 if (!IsNewerThan(*ptxOld))
genesis 346 return false;
genesis 347 for (int i = 0; i < vin.size(); i++)
genesis 348 {
genesis 349 COutPoint outpoint = vin[i].prevout;
genesis 350 if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
genesis 351 return false;
genesis 352 }
genesis 353 break;
genesis 354 }
genesis 355 }
genesis 356
genesis 357 if (fCheckInputs)
genesis 358 {
genesis 359
genesis 360 map<uint256, CTxIndex> mapUnused;
genesis 361 int64 nFees = 0;
genesis 362 bool fInvalid = false;
genesis 363 if (!ConnectInputs(txdb, mapUnused, CDiskTxPos(1,1,1), pindexBest, nFees, false, false, 0, fInvalid))
genesis 364 {
genesis 365 if (fInvalid)
genesis 366 return error("AcceptToMemoryPool() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str());
genesis 367 return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
genesis 368 }
genesis 369
genesis 370
genesis 371 if (nFees < GetMinFee(1000, true, true))
genesis 372 return error("AcceptToMemoryPool() : not enough fees");
genesis 373
genesis 374
genesis 375
genesis 376
genesis 377 if (nFees < MIN_RELAY_TX_FEE)
genesis 378 {
genesis 379 static CCriticalSection cs;
genesis 380 static double dFreeCount;
genesis 381 static int64 nLastTime;
genesis 382 int64 nNow = GetTime();
genesis 383
genesis 384 CRITICAL_BLOCK(cs)
genesis 385 {
genesis 386
genesis 387 dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
genesis 388 nLastTime = nNow;
genesis 389
genesis 390
genesis 391 if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this))
genesis 392 return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
genesis 393 if (fDebug)
genesis 394 printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
genesis 395 dFreeCount += nSize;
genesis 396 }
genesis 397 }
genesis 398 }
genesis 399
genesis 400
genesis 401 CRITICAL_BLOCK(cs_mapTransactions)
genesis 402 {
genesis 403 if (ptxOld)
genesis 404 {
genesis 405 printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
genesis 406 ptxOld->RemoveFromMemoryPool();
genesis 407 }
genesis 408 AddToMemoryPoolUnchecked();
genesis 409 }
genesis 410
genesis 411
genesis 412
genesis 413 if (ptxOld)
genesis 414 EraseFromWallets(ptxOld->GetHash());
genesis 415
genesis 416 printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str());
genesis 417 return true;
genesis 418 }
genesis 419
genesis 420 bool CTransaction::AcceptToMemoryPool(bool fCheckInputs, bool* pfMissingInputs)
genesis 421 {
genesis 422 CTxDB txdb("r");
genesis 423 return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
genesis 424 }
genesis 425
genesis 426 bool CTransaction::AddToMemoryPoolUnchecked()
genesis 427 {
genesis 428
genesis 429
genesis 430 CRITICAL_BLOCK(cs_mapTransactions)
genesis 431 {
genesis 432 uint256 hash = GetHash();
genesis 433 mapTransactions[hash] = *this;
genesis 434 for (int i = 0; i < vin.size(); i++)
genesis 435 mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i);
genesis 436 nTransactionsUpdated++;
genesis 437 }
genesis 438 return true;
genesis 439 }
genesis 440
genesis 441
genesis 442 bool CTransaction::RemoveFromMemoryPool()
genesis 443 {
genesis 444
genesis 445 CRITICAL_BLOCK(cs_mapTransactions)
genesis 446 {
genesis 447 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 448 mapNextTx.erase(txin.prevout);
genesis 449 mapTransactions.erase(GetHash());
genesis 450 nTransactionsUpdated++;
genesis 451 }
genesis 452 return true;
genesis 453 }
genesis 454
genesis 455
genesis 456
genesis 457
genesis 458
genesis 459
genesis 460 int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const
genesis 461 {
genesis 462 if (hashBlock == 0 || nIndex == -1)
genesis 463 return 0;
genesis 464
genesis 465
genesis 466 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
genesis 467 if (mi == mapBlockIndex.end())
genesis 468 return 0;
genesis 469 CBlockIndex* pindex = (*mi).second;
genesis 470 if (!pindex || !pindex->IsInMainChain())
genesis 471 return 0;
genesis 472
genesis 473
genesis 474 if (!fMerkleVerified)
genesis 475 {
genesis 476 if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
genesis 477 return 0;
genesis 478 fMerkleVerified = true;
genesis 479 }
genesis 480
genesis 481 nHeightRet = pindex->nHeight;
genesis 482 return pindexBest->nHeight - pindex->nHeight + 1;
genesis 483 }
genesis 484
genesis 485
genesis 486 int CMerkleTx::GetBlocksToMaturity() const
genesis 487 {
genesis 488 if (!IsCoinBase())
genesis 489 return 0;
genesis 490 return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
genesis 491 }
genesis 492
genesis 493
genesis 494 bool CMerkleTx::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs)
genesis 495 {
genesis 496 if (fClient)
genesis 497 {
genesis 498 if (!IsInMainChain() && !ClientConnectInputs())
genesis 499 return false;
genesis 500 return CTransaction::AcceptToMemoryPool(txdb, false);
genesis 501 }
genesis 502 else
genesis 503 {
genesis 504 return CTransaction::AcceptToMemoryPool(txdb, fCheckInputs);
genesis 505 }
genesis 506 }
genesis 507
genesis 508 bool CMerkleTx::AcceptToMemoryPool()
genesis 509 {
genesis 510 CTxDB txdb("r");
genesis 511 return AcceptToMemoryPool(txdb);
genesis 512 }
genesis 513
genesis 514
genesis 515
genesis 516 bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
genesis 517 {
genesis 518 CRITICAL_BLOCK(cs_mapTransactions)
genesis 519 {
genesis 520
genesis 521 BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
genesis 522 {
genesis 523 if (!tx.IsCoinBase())
genesis 524 {
genesis 525 uint256 hash = tx.GetHash();
genesis 526 if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))
genesis 527 tx.AcceptToMemoryPool(txdb, fCheckInputs);
genesis 528 }
genesis 529 }
genesis 530 return AcceptToMemoryPool(txdb, fCheckInputs);
genesis 531 }
genesis 532 return false;
genesis 533 }
genesis 534
genesis 535 bool CWalletTx::AcceptWalletTransaction()
genesis 536 {
genesis 537 CTxDB txdb("r");
genesis 538 return AcceptWalletTransaction(txdb);
genesis 539 }
genesis 540
genesis 541 int CTxIndex::GetDepthInMainChain() const
genesis 542 {
genesis 543
genesis 544 CBlock block;
genesis 545 if (!block.ReadFromDisk(pos.nFile, pos.nBlockPos, false))
genesis 546 return 0;
genesis 547
genesis 548 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.GetHash());
genesis 549 if (mi == mapBlockIndex.end())
genesis 550 return 0;
genesis 551 CBlockIndex* pindex = (*mi).second;
genesis 552 if (!pindex || !pindex->IsInMainChain())
genesis 553 return 0;
genesis 554 return 1 + nBestHeight - pindex->nHeight;
genesis 555 }
genesis 556
genesis 557
genesis 558
genesis 559
genesis 560
genesis 561
genesis 562
genesis 563
genesis 564
genesis 565
genesis 566
genesis 567
genesis 568
genesis 569
genesis 570
genesis 571 bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
genesis 572 {
genesis 573 if (!fReadTransactions)
genesis 574 {
genesis 575 *this = pindex->GetBlockHeader();
genesis 576 return true;
genesis 577 }
genesis 578 if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions))
genesis 579 return false;
genesis 580 if (GetHash() != pindex->GetBlockHash())
genesis 581 return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
genesis 582 return true;
genesis 583 }
genesis 584
genesis 585 int64 static GetBlockValue(int nHeight, int64 nFees)
genesis 586 {
genesis 587 int64 nSubsidy = 50 * COIN;
genesis 588
genesis 589
genesis 590 nSubsidy >>= (nHeight / 210000);
genesis 591
genesis 592 return nSubsidy + nFees;
genesis 593 }
genesis 594
genesis 595 static const int64 nTargetTimespan = 14 * 24 * 60 * 60;
genesis 596 static const int64 nTargetSpacing = 10 * 60;
genesis 597 static const int64 nInterval = nTargetTimespan / nTargetSpacing;
genesis 598
genesis 599
genesis 600
genesis 601
genesis 602
genesis 603 unsigned int ComputeMinWork(unsigned int nBase, int64 nTime)
genesis 604 {
genesis 605 CBigNum bnResult;
genesis 606 bnResult.SetCompact(nBase);
genesis 607 while (nTime > 0 && bnResult < bnProofOfWorkLimit)
genesis 608 {
genesis 609
genesis 610 bnResult *= 4;
genesis 611
genesis 612 nTime -= nTargetTimespan*4;
genesis 613 }
genesis 614 if (bnResult > bnProofOfWorkLimit)
genesis 615 bnResult = bnProofOfWorkLimit;
genesis 616 return bnResult.GetCompact();
genesis 617 }
genesis 618
genesis 619 unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlock *pblock)
genesis 620 {
genesis 621 unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact();
genesis 622
genesis 623
genesis 624 if (pindexLast == NULL)
genesis 625 return nProofOfWorkLimit;
genesis 626
genesis 627
genesis 628 if ((pindexLast->nHeight+1) % nInterval != 0)
genesis 629 {
genesis 630 return pindexLast->nBits;
genesis 631 }
genesis 632
genesis 633
genesis 634 const CBlockIndex* pindexFirst = pindexLast;
genesis 635 for (int i = 0; pindexFirst && i < nInterval-1; i++)
genesis 636 pindexFirst = pindexFirst->pprev;
genesis 637 assert(pindexFirst);
genesis 638
genesis 639
genesis 640 int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
genesis 641 printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
genesis 642 if (nActualTimespan < nTargetTimespan/4)
genesis 643 nActualTimespan = nTargetTimespan/4;
genesis 644 if (nActualTimespan > nTargetTimespan*4)
genesis 645 nActualTimespan = nTargetTimespan*4;
genesis 646
genesis 647
genesis 648 CBigNum bnNew;
genesis 649 bnNew.SetCompact(pindexLast->nBits);
genesis 650 bnNew *= nActualTimespan;
genesis 651 bnNew /= nTargetTimespan;
genesis 652
genesis 653 if (bnNew > bnProofOfWorkLimit)
genesis 654 bnNew = bnProofOfWorkLimit;
genesis 655
genesis 656
genesis 657 printf("GetNextWorkRequired RETARGET\n");
genesis 658 printf("nTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"\n", nTargetTimespan, nActualTimespan);
genesis 659 printf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str());
genesis 660 printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
genesis 661
genesis 662 return bnNew.GetCompact();
genesis 663 }
genesis 664
genesis 665 bool CheckProofOfWork(uint256 hash, unsigned int nBits)
genesis 666 {
genesis 667 CBigNum bnTarget;
genesis 668 bnTarget.SetCompact(nBits);
genesis 669
genesis 670
genesis 671 if (bnTarget <= 0 || bnTarget > bnProofOfWorkLimit)
genesis 672 return error("CheckProofOfWork() : nBits below minimum work");
genesis 673
genesis 674
genesis 675 if (hash > bnTarget.getuint256())
genesis 676 return error("CheckProofOfWork() : hash doesn't match nBits");
genesis 677
genesis 678 return true;
genesis 679 }
genesis 680
genesis 681
genesis 682 int GetNumBlocksOfPeers()
genesis 683 {
genesis 684 return std::max(cPeerBlockCounts.median(), Checkpoints::GetTotalBlocksEstimate());
genesis 685 }
genesis 686
genesis 687 bool IsInitialBlockDownload()
genesis 688 {
genesis 689 if (pindexBest == NULL || nBestHeight < Checkpoints::GetTotalBlocksEstimate())
genesis 690 return true;
genesis 691 static int64 nLastUpdate;
genesis 692 static CBlockIndex* pindexLastBest;
genesis 693 if (pindexBest != pindexLastBest)
genesis 694 {
genesis 695 pindexLastBest = pindexBest;
genesis 696 nLastUpdate = GetTime();
genesis 697 }
genesis 698 return (GetTime() - nLastUpdate < 10 &&
genesis 699 pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
genesis 700 }
genesis 701
genesis 702 void static InvalidChainFound(CBlockIndex* pindexNew)
genesis 703 {
genesis 704 if (pindexNew->bnChainWork > bnBestInvalidWork)
genesis 705 {
genesis 706 bnBestInvalidWork = pindexNew->bnChainWork;
genesis 707 CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
genesis 708 MainFrameRepaint();
genesis 709 }
genesis 710 printf("InvalidChainFound: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
genesis 711 printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
genesis 712 if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
genesis 713 printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
genesis 714 }
genesis 715
genesis 716
genesis 717
genesis 718
genesis 719
genesis 720
genesis 721
genesis 722
genesis 723
genesis 724
genesis 725
genesis 726 bool CTransaction::DisconnectInputs(CTxDB& txdb)
genesis 727 {
genesis 728
genesis 729 if (!IsCoinBase())
genesis 730 {
genesis 731 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 732 {
genesis 733 COutPoint prevout = txin.prevout;
genesis 734
genesis 735
genesis 736 CTxIndex txindex;
genesis 737 if (!txdb.ReadTxIndex(prevout.hash, txindex))
genesis 738 return error("DisconnectInputs() : ReadTxIndex failed");
genesis 739
genesis 740 if (prevout.n >= txindex.vSpent.size())
genesis 741 return error("DisconnectInputs() : prevout.n out of range");
genesis 742
genesis 743
genesis 744 txindex.vSpent[prevout.n].SetNull();
genesis 745
genesis 746
genesis 747 if (!txdb.UpdateTxIndex(prevout.hash, txindex))
genesis 748 return error("DisconnectInputs() : UpdateTxIndex failed");
genesis 749 }
genesis 750 }
genesis 751
genesis 752
genesis 753
genesis 754
genesis 755
genesis 756 txdb.EraseTxIndex(*this);
genesis 757
genesis 758 return true;
genesis 759 }
genesis 760
genesis 761
genesis 762 bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
genesis 763 CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee,
genesis 764 bool& fInvalid)
genesis 765 {
genesis 766
genesis 767
genesis 768
genesis 769
genesis 770 fInvalid = false;
genesis 771
genesis 772
genesis 773
genesis 774
genesis 775
genesis 776 if (!IsCoinBase())
genesis 777 {
genesis 778 int64 nValueIn = 0;
genesis 779 for (int i = 0; i < vin.size(); i++)
genesis 780 {
genesis 781 COutPoint prevout = vin[i].prevout;
genesis 782
genesis 783
genesis 784 CTxIndex txindex;
genesis 785 bool fFound = true;
genesis 786 if ((fBlock || fMiner) && mapTestPool.count(prevout.hash))
genesis 787 {
genesis 788
genesis 789 txindex = mapTestPool[prevout.hash];
genesis 790 }
genesis 791 else
genesis 792 {
genesis 793
genesis 794 fFound = txdb.ReadTxIndex(prevout.hash, txindex);
genesis 795 }
genesis 796 if (!fFound && (fBlock || fMiner))
genesis 797 return fMiner ? false : error("ConnectInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
genesis 798
genesis 799
genesis 800 CTransaction txPrev;
genesis 801 if (!fFound || txindex.pos == CDiskTxPos(1,1,1))
genesis 802 {
genesis 803
genesis 804 CRITICAL_BLOCK(cs_mapTransactions)
genesis 805 {
genesis 806 if (!mapTransactions.count(prevout.hash))
genesis 807 return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
genesis 808 txPrev = mapTransactions[prevout.hash];
genesis 809 }
genesis 810 if (!fFound)
genesis 811 txindex.vSpent.resize(txPrev.vout.size());
genesis 812 }
genesis 813 else
genesis 814 {
genesis 815
genesis 816 if (!txPrev.ReadFromDisk(txindex.pos))
genesis 817 return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
genesis 818 }
genesis 819
genesis 820 if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
genesis 821 {
genesis 822
genesis 823
genesis 824 fInvalid = true;
genesis 825 return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %d %d prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
genesis 826 }
genesis 827
genesis 828
genesis 829 if (txPrev.IsCoinBase())
genesis 830 for (CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < COINBASE_MATURITY; pindex = pindex->pprev)
genesis 831 if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
genesis 832 return error("ConnectInputs() : tried to spend coinbase at depth %d", pindexBlock->nHeight - pindex->nHeight);
genesis 833
genesis 834
genesis 835
genesis 836
asciilifeform_add... 837 if (fVerifyAll || (!(fBlock && (nBestHeight < Checkpoints::GetTotalBlocksEstimate()))))
genesis 838
genesis 839 if (!VerifySignature(txPrev, *this, i))
genesis 840 return DoS(100,error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str()));
genesis 841
genesis 842
genesis 843
genesis 844
genesis 845 if (!txindex.vSpent[prevout.n].IsNull())
genesis 846 return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,10).c_str(), txindex.vSpent[prevout.n].ToString().c_str());
genesis 847
genesis 848
genesis 849 nValueIn += txPrev.vout[prevout.n].nValue;
genesis 850 if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
genesis 851 return DoS(100, error("ConnectInputs() : txin values out of range"));
genesis 852
genesis 853
genesis 854 txindex.vSpent[prevout.n] = posThisTx;
genesis 855
genesis 856
genesis 857 if (fBlock || fMiner)
genesis 858 {
genesis 859 mapTestPool[prevout.hash] = txindex;
genesis 860 }
genesis 861 }
genesis 862
genesis 863 if (nValueIn < GetValueOut())
genesis 864 return DoS(100, error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,10).c_str()));
genesis 865
genesis 866
genesis 867 int64 nTxFee = nValueIn - GetValueOut();
genesis 868 if (nTxFee < 0)
genesis 869 return DoS(100, error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,10).c_str()));
genesis 870 if (nTxFee < nMinFee)
genesis 871 return false;
genesis 872 nFees += nTxFee;
genesis 873 if (!MoneyRange(nFees))
genesis 874 return DoS(100, error("ConnectInputs() : nFees out of range"));
genesis 875 }
genesis 876
genesis 877 if (fBlock)
genesis 878 {
genesis 879
genesis 880 mapTestPool[GetHash()] = CTxIndex(posThisTx, vout.size());
genesis 881 }
genesis 882 else if (fMiner)
genesis 883 {
genesis 884
genesis 885 mapTestPool[GetHash()] = CTxIndex(CDiskTxPos(1,1,1), vout.size());
genesis 886 }
genesis 887
genesis 888 return true;
genesis 889 }
genesis 890
genesis 891
genesis 892 bool CTransaction::ClientConnectInputs()
genesis 893 {
genesis 894 if (IsCoinBase())
genesis 895 return false;
genesis 896
genesis 897
genesis 898 CRITICAL_BLOCK(cs_mapTransactions)
genesis 899 {
genesis 900 int64 nValueIn = 0;
genesis 901 for (int i = 0; i < vin.size(); i++)
genesis 902 {
genesis 903
genesis 904 COutPoint prevout = vin[i].prevout;
genesis 905 if (!mapTransactions.count(prevout.hash))
genesis 906 return false;
genesis 907 CTransaction& txPrev = mapTransactions[prevout.hash];
genesis 908
genesis 909 if (prevout.n >= txPrev.vout.size())
genesis 910 return false;
genesis 911
genesis 912
genesis 913 if (!VerifySignature(txPrev, *this, i))
genesis 914 return error("ConnectInputs() : VerifySignature failed");
genesis 915
genesis 916
genesis 917
genesis 918
genesis 919
genesis 920
genesis 921
genesis 922
genesis 923
genesis 924
genesis 925 nValueIn += txPrev.vout[prevout.n].nValue;
genesis 926
genesis 927 if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
genesis 928 return error("ClientConnectInputs() : txin values out of range");
genesis 929 }
genesis 930 if (GetValueOut() > nValueIn)
genesis 931 return false;
genesis 932 }
genesis 933
genesis 934 return true;
genesis 935 }
genesis 936
genesis 937
genesis 938
genesis 939
genesis 940 bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
genesis 941 {
genesis 942
genesis 943 for (int i = vtx.size()-1; i >= 0; i--)
genesis 944 if (!vtx[i].DisconnectInputs(txdb))
genesis 945 return false;
genesis 946
genesis 947
genesis 948
genesis 949 if (pindex->pprev)
genesis 950 {
genesis 951 CDiskBlockIndex blockindexPrev(pindex->pprev);
genesis 952 blockindexPrev.hashNext = 0;
genesis 953 if (!txdb.WriteBlockIndex(blockindexPrev))
genesis 954 return error("DisconnectBlock() : WriteBlockIndex failed");
genesis 955 }
genesis 956
genesis 957 return true;
genesis 958 }
genesis 959
genesis 960 bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
genesis 961 {
genesis 962
genesis 963 if (!CheckBlock())
genesis 964 return false;
genesis 965
genesis 966
genesis 967
genesis 968
genesis 969
genesis 970
genesis 971
genesis 972
genesis 973
genesis 974
asciilifeform_let... 975 if (pindex->nTime > 1331769600)
genesis 976 BOOST_FOREACH(CTransaction& tx, vtx)
genesis 977 {
genesis 978 CTxIndex txindexOld;
genesis 979 if (txdb.ReadTxIndex(tx.GetHash(), txindexOld))
genesis 980 BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent)
genesis 981 if (pos.IsNull())
genesis 982 return false;
genesis 983 }
genesis 984
genesis 985
genesis 986 unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK) - 1 + GetSizeOfCompactSize(vtx.size());
genesis 987
genesis 988 map<uint256, CTxIndex> mapQueuedChanges;
genesis 989 int64 nFees = 0;
genesis 990 BOOST_FOREACH(CTransaction& tx, vtx)
genesis 991 {
genesis 992 CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
genesis 993 nTxPos += ::GetSerializeSize(tx, SER_DISK);
genesis 994
genesis 995 bool fInvalid;
genesis 996 if (!tx.ConnectInputs(txdb, mapQueuedChanges, posThisTx, pindex, nFees, true, false, 0, fInvalid))
genesis 997 return false;
genesis 998 }
genesis 999
genesis 1000 for (map<uint256, CTxIndex>::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi)
genesis 1001 {
genesis 1002 if (!txdb.UpdateTxIndex((*mi).first, (*mi).second))
genesis 1003 return error("ConnectBlock() : UpdateTxIndex failed");
genesis 1004 }
genesis 1005
genesis 1006 if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
genesis 1007 return false;
genesis 1008
genesis 1009
genesis 1010
genesis 1011 if (pindex->pprev)
genesis 1012 {
genesis 1013 CDiskBlockIndex blockindexPrev(pindex->pprev);
genesis 1014 blockindexPrev.hashNext = pindex->GetBlockHash();
genesis 1015 if (!txdb.WriteBlockIndex(blockindexPrev))
genesis 1016 return error("ConnectBlock() : WriteBlockIndex failed");
genesis 1017 }
genesis 1018
genesis 1019
genesis 1020 BOOST_FOREACH(CTransaction& tx, vtx)
genesis 1021 SyncWithWallets(tx, this, true);
genesis 1022
genesis 1023 return true;
genesis 1024 }
genesis 1025
genesis 1026 bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
genesis 1027 {
genesis 1028 printf("REORGANIZE\n");
genesis 1029
genesis 1030
genesis 1031 CBlockIndex* pfork = pindexBest;
genesis 1032 CBlockIndex* plonger = pindexNew;
genesis 1033 while (pfork != plonger)
genesis 1034 {
genesis 1035 while (plonger->nHeight > pfork->nHeight)
genesis 1036 if (!(plonger = plonger->pprev))
genesis 1037 return error("Reorganize() : plonger->pprev is null");
genesis 1038 if (pfork == plonger)
genesis 1039 break;
genesis 1040 if (!(pfork = pfork->pprev))
genesis 1041 return error("Reorganize() : pfork->pprev is null");
genesis 1042 }
genesis 1043
genesis 1044
genesis 1045 vector<CBlockIndex*> vDisconnect;
genesis 1046 for (CBlockIndex* pindex = pindexBest; pindex != pfork; pindex = pindex->pprev)
genesis 1047 vDisconnect.push_back(pindex);
genesis 1048
genesis 1049
genesis 1050 vector<CBlockIndex*> vConnect;
genesis 1051 for (CBlockIndex* pindex = pindexNew; pindex != pfork; pindex = pindex->pprev)
genesis 1052 vConnect.push_back(pindex);
genesis 1053 reverse(vConnect.begin(), vConnect.end());
genesis 1054
genesis 1055
genesis 1056 vector<CTransaction> vResurrect;
genesis 1057 BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
genesis 1058 {
genesis 1059 CBlock block;
genesis 1060 if (!block.ReadFromDisk(pindex))
genesis 1061 return error("Reorganize() : ReadFromDisk for disconnect failed");
genesis 1062 if (!block.DisconnectBlock(txdb, pindex))
genesis 1063 return error("Reorganize() : DisconnectBlock failed");
genesis 1064
genesis 1065
genesis 1066 BOOST_FOREACH(const CTransaction& tx, block.vtx)
genesis 1067 if (!tx.IsCoinBase())
genesis 1068 vResurrect.push_back(tx);
genesis 1069 }
genesis 1070
genesis 1071
genesis 1072 vector<CTransaction> vDelete;
genesis 1073 for (int i = 0; i < vConnect.size(); i++)
genesis 1074 {
genesis 1075 CBlockIndex* pindex = vConnect[i];
genesis 1076 CBlock block;
genesis 1077 if (!block.ReadFromDisk(pindex))
genesis 1078 return error("Reorganize() : ReadFromDisk for connect failed");
genesis 1079 if (!block.ConnectBlock(txdb, pindex))
genesis 1080 {
genesis 1081
genesis 1082 txdb.TxnAbort();
genesis 1083 return error("Reorganize() : ConnectBlock failed");
genesis 1084 }
genesis 1085
genesis 1086
genesis 1087 BOOST_FOREACH(const CTransaction& tx, block.vtx)
genesis 1088 vDelete.push_back(tx);
genesis 1089 }
genesis 1090 if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash()))
genesis 1091 return error("Reorganize() : WriteHashBestChain failed");
genesis 1092
genesis 1093
genesis 1094 if (!txdb.TxnCommit())
genesis 1095 return error("Reorganize() : TxnCommit failed");
genesis 1096
genesis 1097
genesis 1098 BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
genesis 1099 if (pindex->pprev)
genesis 1100 pindex->pprev->pnext = NULL;
genesis 1101
genesis 1102
genesis 1103 BOOST_FOREACH(CBlockIndex* pindex, vConnect)
genesis 1104 if (pindex->pprev)
genesis 1105 pindex->pprev->pnext = pindex;
genesis 1106
genesis 1107
genesis 1108 BOOST_FOREACH(CTransaction& tx, vResurrect)
genesis 1109 tx.AcceptToMemoryPool(txdb, false);
genesis 1110
genesis 1111
genesis 1112 BOOST_FOREACH(CTransaction& tx, vDelete)
genesis 1113 tx.RemoveFromMemoryPool();
genesis 1114
genesis 1115 return true;
genesis 1116 }
genesis 1117
genesis 1118
genesis 1119 bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
genesis 1120 {
genesis 1121 uint256 hash = GetHash();
genesis 1122
genesis 1123 txdb.TxnBegin();
genesis 1124 if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
genesis 1125 {
genesis 1126 txdb.WriteHashBestChain(hash);
genesis 1127 if (!txdb.TxnCommit())
genesis 1128 return error("SetBestChain() : TxnCommit failed");
genesis 1129 pindexGenesisBlock = pindexNew;
genesis 1130 }
genesis 1131 else if (hashPrevBlock == hashBestChain)
genesis 1132 {
genesis 1133
genesis 1134 if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
genesis 1135 {
genesis 1136 txdb.TxnAbort();
genesis 1137 InvalidChainFound(pindexNew);
genesis 1138 return error("SetBestChain() : ConnectBlock failed");
genesis 1139 }
genesis 1140 if (!txdb.TxnCommit())
genesis 1141 return error("SetBestChain() : TxnCommit failed");
genesis 1142
genesis 1143
genesis 1144 pindexNew->pprev->pnext = pindexNew;
genesis 1145
genesis 1146
genesis 1147 BOOST_FOREACH(CTransaction& tx, vtx)
genesis 1148 tx.RemoveFromMemoryPool();
genesis 1149 }
genesis 1150 else
genesis 1151 {
genesis 1152
genesis 1153 if (!Reorganize(txdb, pindexNew))
genesis 1154 {
genesis 1155 txdb.TxnAbort();
genesis 1156 InvalidChainFound(pindexNew);
genesis 1157 return error("SetBestChain() : Reorganize failed");
genesis 1158 }
genesis 1159 }
genesis 1160
genesis 1161
genesis 1162 if (!IsInitialBlockDownload())
genesis 1163 {
genesis 1164 const CBlockLocator locator(pindexNew);
genesis 1165 ::SetBestChain(locator);
genesis 1166 }
genesis 1167
genesis 1168
genesis 1169 hashBestChain = hash;
genesis 1170 pindexBest = pindexNew;
genesis 1171 nBestHeight = pindexBest->nHeight;
genesis 1172 bnBestChainWork = pindexNew->bnChainWork;
genesis 1173 nTimeBestReceived = GetTime();
genesis 1174 nTransactionsUpdated++;
genesis 1175 printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
genesis 1176
genesis 1177 return true;
genesis 1178 }
genesis 1179
genesis 1180
genesis 1181 bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
genesis 1182 {
genesis 1183
genesis 1184 uint256 hash = GetHash();
genesis 1185 if (mapBlockIndex.count(hash))
genesis 1186 return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,20).c_str());
genesis 1187
genesis 1188
genesis 1189 CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
genesis 1190 if (!pindexNew)
genesis 1191 return error("AddToBlockIndex() : new CBlockIndex failed");
genesis 1192 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
genesis 1193 pindexNew->phashBlock = &((*mi).first);
genesis 1194 map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
genesis 1195 if (miPrev != mapBlockIndex.end())
genesis 1196 {
genesis 1197 pindexNew->pprev = (*miPrev).second;
genesis 1198 pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
genesis 1199 }
genesis 1200 pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork();
genesis 1201
genesis 1202 CTxDB txdb;
genesis 1203 txdb.TxnBegin();
genesis 1204 txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
genesis 1205 if (!txdb.TxnCommit())
genesis 1206 return false;
genesis 1207
genesis 1208
genesis 1209 if (pindexNew->bnChainWork > bnBestChainWork)
genesis 1210 if (!SetBestChain(txdb, pindexNew))
genesis 1211 return false;
genesis 1212
genesis 1213 txdb.Close();
genesis 1214
genesis 1215 if (pindexNew == pindexBest)
genesis 1216 {
genesis 1217
genesis 1218 static uint256 hashPrevBestCoinBase;
genesis 1219 UpdatedTransaction(hashPrevBestCoinBase);
genesis 1220 hashPrevBestCoinBase = vtx[0].GetHash();
genesis 1221 }
genesis 1222
genesis 1223 MainFrameRepaint();
genesis 1224 return true;
genesis 1225 }
genesis 1226
genesis 1227
genesis 1228
genesis 1229
genesis 1230 bool CBlock::CheckBlock() const
genesis 1231 {
genesis 1232
genesis 1233
genesis 1234
genesis 1235
genesis 1236 if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE)
genesis 1237 return DoS(100, error("CheckBlock() : size limits failed"));
genesis 1238
genesis 1239
genesis 1240 if (!CheckProofOfWork(GetHash(), nBits))
genesis 1241 return DoS(50, error("CheckBlock() : proof of work failed"));
genesis 1242
genesis 1243
genesis 1244 if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
genesis 1245 return error("CheckBlock() : block timestamp too far in the future");
genesis 1246
genesis 1247
genesis 1248 if (vtx.empty() || !vtx[0].IsCoinBase())
genesis 1249 return DoS(100, error("CheckBlock() : first tx is not coinbase"));
genesis 1250 for (int i = 1; i < vtx.size(); i++)
genesis 1251 if (vtx[i].IsCoinBase())
genesis 1252 return DoS(100, error("CheckBlock() : more than one coinbase"));
genesis 1253
genesis 1254
genesis 1255 BOOST_FOREACH(const CTransaction& tx, vtx)
genesis 1256 if (!tx.CheckTransaction())
genesis 1257 return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
genesis 1258
genesis 1259
genesis 1260 if (GetSigOpCount() > MAX_BLOCK_SIGOPS)
genesis 1261 return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
genesis 1262
genesis 1263
genesis 1264 if (hashMerkleRoot != BuildMerkleTree())
genesis 1265 return DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
genesis 1266
genesis 1267 return true;
genesis 1268 }
genesis 1269
genesis 1270 bool CBlock::AcceptBlock()
genesis 1271 {
genesis 1272
genesis 1273 uint256 hash = GetHash();
genesis 1274 if (mapBlockIndex.count(hash))
genesis 1275 return error("AcceptBlock() : block already in mapBlockIndex");
genesis 1276
genesis 1277
genesis 1278 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
genesis 1279 if (mi == mapBlockIndex.end())
genesis 1280 return DoS(10, error("AcceptBlock() : prev block not found"));
genesis 1281 CBlockIndex* pindexPrev = (*mi).second;
genesis 1282 int nHeight = pindexPrev->nHeight+1;
genesis 1283
genesis 1284
genesis 1285 if (nBits != GetNextWorkRequired(pindexPrev, this))
genesis 1286 return DoS(100, error("AcceptBlock() : incorrect proof of work"));
genesis 1287
genesis 1288
genesis 1289 if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
genesis 1290 return error("AcceptBlock() : block's timestamp is too early");
genesis 1291
genesis 1292
genesis 1293 BOOST_FOREACH(const CTransaction& tx, vtx)
genesis 1294 if (!tx.IsFinal(nHeight, GetBlockTime()))
genesis 1295 return DoS(10, error("AcceptBlock() : contains a non-final transaction"));
genesis 1296
genesis 1297
genesis 1298 if (!Checkpoints::CheckBlock(nHeight, hash))
genesis 1299 return DoS(100, error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight));
genesis 1300
genesis 1301
genesis 1302 if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
genesis 1303 return error("AcceptBlock() : out of disk space");
genesis 1304 unsigned int nFile = -1;
genesis 1305 unsigned int nBlockPos = 0;
genesis 1306 if (!WriteToDisk(nFile, nBlockPos))
genesis 1307 return error("AcceptBlock() : WriteToDisk failed");
genesis 1308 if (!AddToBlockIndex(nFile, nBlockPos))
genesis 1309 return error("AcceptBlock() : AddToBlockIndex failed");
genesis 1310
genesis 1311
genesis 1312 if (hashBestChain == hash)
genesis 1313 CRITICAL_BLOCK(cs_vNodes)
genesis 1314 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1315 if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 140700))
genesis 1316 pnode->PushInventory(CInv(MSG_BLOCK, hash));
genesis 1317
genesis 1318 return true;
genesis 1319 }
genesis 1320
genesis 1321 bool ProcessBlock(CNode* pfrom, CBlock* pblock)
genesis 1322 {
genesis 1323
genesis 1324 uint256 hash = pblock->GetHash();
genesis 1325 if (mapBlockIndex.count(hash))
genesis 1326 return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,20).c_str());
genesis 1327
genesis 1328
genesis 1329 if (!pblock->CheckBlock())
genesis 1330 return error("ProcessBlock() : CheckBlock FAILED");
genesis 1331
genesis 1332 CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
genesis 1333 if (pcheckpoint && pblock->hashPrevBlock != hashBestChain)
genesis 1334 {
genesis 1335
genesis 1336 int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
genesis 1337 if (deltaTime < 0)
genesis 1338 {
genesis 1339 if (pfrom)
genesis 1340 pfrom->Misbehaving(100);
genesis 1341 return error("ProcessBlock() : block with timestamp before last checkpoint");
genesis 1342 }
genesis 1343 CBigNum bnNewBlock;
genesis 1344 bnNewBlock.SetCompact(pblock->nBits);
genesis 1345 CBigNum bnRequired;
genesis 1346 bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
genesis 1347 if (bnNewBlock > bnRequired)
genesis 1348 {
genesis 1349 if (pfrom)
genesis 1350 pfrom->Misbehaving(100);
genesis 1351 return error("ProcessBlock() : block with too little proof-of-work");
genesis 1352 }
genesis 1353 }
genesis 1354
asciilifeform_orp... 1355
genesis 1356 if (!mapBlockIndex.count(pblock->hashPrevBlock))
genesis 1357 {
asciilifeform_orp... 1358 printf("ProcessBlock: BASTARD BLOCK, prev=%s, DISCARDED\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str());
genesis 1359
genesis 1360
genesis 1361 if (pfrom)
asciilifeform_orp... 1362 pfrom->PushGetBlocks(pindexBest, pblock->hashPrevBlock);
asciilifeform_orp... 1363
asciilifeform_orp... 1364 return true;
genesis 1365 }
genesis 1366
genesis 1367
genesis 1368 if (!pblock->AcceptBlock())
genesis 1369 return error("ProcessBlock() : AcceptBlock FAILED");
genesis 1370
genesis 1371 printf("ProcessBlock: ACCEPTED\n");
genesis 1372 return true;
genesis 1373 }
genesis 1374
genesis 1375
genesis 1376
genesis 1377
genesis 1378
genesis 1379
genesis 1380
genesis 1381
genesis 1382 bool CheckDiskSpace(uint64 nAdditionalBytes)
genesis 1383 {
genesis 1384 uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
genesis 1385
genesis 1386
genesis 1387 if (nFreeBytesAvailable < (uint64)15000000 + nAdditionalBytes)
genesis 1388 {
genesis 1389 fShutdown = true;
genesis 1390 string strMessage = _("Warning: Disk space is low ");
genesis 1391 strMiscWarning = strMessage;
genesis 1392 printf("*** %s\n", strMessage.c_str());
genesis 1393 ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
genesis 1394 CreateThread(Shutdown, NULL);
genesis 1395 return false;
genesis 1396 }
genesis 1397 return true;
genesis 1398 }
genesis 1399
genesis 1400 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode)
genesis 1401 {
genesis 1402 if (nFile == -1)
genesis 1403 return NULL;
genesis 1404 FILE* file = fopen(strprintf("%s/blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
genesis 1405 if (!file)
genesis 1406 return NULL;
genesis 1407 if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
genesis 1408 {
genesis 1409 if (fseek(file, nBlockPos, SEEK_SET) != 0)
genesis 1410 {
genesis 1411 fclose(file);
genesis 1412 return NULL;
genesis 1413 }
genesis 1414 }
genesis 1415 return file;
genesis 1416 }
genesis 1417
genesis 1418 static unsigned int nCurrentBlockFile = 1;
genesis 1419
genesis 1420 FILE* AppendBlockFile(unsigned int& nFileRet)
genesis 1421 {
genesis 1422 nFileRet = 0;
genesis 1423 loop
genesis 1424 {
genesis 1425 FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab");
genesis 1426 if (!file)
genesis 1427 return NULL;
genesis 1428 if (fseek(file, 0, SEEK_END) != 0)
genesis 1429 return NULL;
genesis 1430
genesis 1431 if (ftell(file) < 0x7F000000 - MAX_SIZE)
genesis 1432 {
genesis 1433 nFileRet = nCurrentBlockFile;
genesis 1434 return file;
genesis 1435 }
genesis 1436 fclose(file);
genesis 1437 nCurrentBlockFile++;
genesis 1438 }
genesis 1439 }
genesis 1440
genesis 1441 bool LoadBlockIndex(bool fAllowNew)
genesis 1442 {
genesis 1443
genesis 1444
genesis 1445
genesis 1446 CTxDB txdb("cr");
genesis 1447 if (!txdb.LoadBlockIndex())
genesis 1448 return false;
genesis 1449 txdb.Close();
genesis 1450
genesis 1451
genesis 1452
genesis 1453
genesis 1454 if (mapBlockIndex.empty())
genesis 1455 {
genesis 1456 if (!fAllowNew)
genesis 1457 return false;
genesis 1458
genesis 1459
genesis 1460
genesis 1461
genesis 1462
genesis 1463
genesis 1464
genesis 1465
genesis 1466
genesis 1467 const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
genesis 1468 CTransaction txNew;
genesis 1469 txNew.vin.resize(1);
genesis 1470 txNew.vout.resize(1);
genesis 1471 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
genesis 1472 txNew.vout[0].nValue = 50 * COIN;
genesis 1473 txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
genesis 1474 CBlock block;
genesis 1475 block.vtx.push_back(txNew);
genesis 1476 block.hashPrevBlock = 0;
genesis 1477 block.hashMerkleRoot = block.BuildMerkleTree();
genesis 1478 block.nVersion = 1;
genesis 1479 block.nTime = 1231006505;
genesis 1480 block.nBits = 0x1d00ffff;
genesis 1481 block.nNonce = 2083236893;
genesis 1482
genesis 1483
genesis 1484 printf("%s\n", block.GetHash().ToString().c_str());
genesis 1485 printf("%s\n", hashGenesisBlock.ToString().c_str());
genesis 1486 printf("%s\n", block.hashMerkleRoot.ToString().c_str());
genesis 1487 assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
genesis 1488 block.print();
genesis 1489 assert(block.GetHash() == hashGenesisBlock);
genesis 1490
genesis 1491
genesis 1492 unsigned int nFile;
genesis 1493 unsigned int nBlockPos;
genesis 1494 if (!block.WriteToDisk(nFile, nBlockPos))
genesis 1495 return error("LoadBlockIndex() : writing genesis block to disk failed");
genesis 1496 if (!block.AddToBlockIndex(nFile, nBlockPos))
genesis 1497 return error("LoadBlockIndex() : genesis block not accepted");
genesis 1498 }
genesis 1499
genesis 1500 return true;
genesis 1501 }
genesis 1502
genesis 1503
genesis 1504
genesis 1505 void PrintBlockTree()
genesis 1506 {
genesis 1507
genesis 1508 map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
genesis 1509 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
genesis 1510 {
genesis 1511 CBlockIndex* pindex = (*mi).second;
genesis 1512 mapNext[pindex->pprev].push_back(pindex);
genesis 1513
genesis 1514
genesis 1515
genesis 1516 }
genesis 1517
genesis 1518 vector<pair<int, CBlockIndex*> > vStack;
genesis 1519 vStack.push_back(make_pair(0, pindexGenesisBlock));
genesis 1520
genesis 1521 int nPrevCol = 0;
genesis 1522 while (!vStack.empty())
genesis 1523 {
genesis 1524 int nCol = vStack.back().first;
genesis 1525 CBlockIndex* pindex = vStack.back().second;
genesis 1526 vStack.pop_back();
genesis 1527
genesis 1528
genesis 1529 if (nCol > nPrevCol)
genesis 1530 {
genesis 1531 for (int i = 0; i < nCol-1; i++)
genesis 1532 printf("| ");
genesis 1533 printf("|\\\n");
genesis 1534 }
genesis 1535 else if (nCol < nPrevCol)
genesis 1536 {
genesis 1537 for (int i = 0; i < nCol; i++)
genesis 1538 printf("| ");
genesis 1539 printf("|\n");
genesis 1540 }
genesis 1541 nPrevCol = nCol;
genesis 1542
genesis 1543
genesis 1544 for (int i = 0; i < nCol; i++)
genesis 1545 printf("| ");
genesis 1546
genesis 1547
genesis 1548 CBlock block;
genesis 1549 block.ReadFromDisk(pindex);
genesis 1550 printf("%d (%u,%u) %s %s tx %d",
genesis 1551 pindex->nHeight,
genesis 1552 pindex->nFile,
genesis 1553 pindex->nBlockPos,
genesis 1554 block.GetHash().ToString().substr(0,20).c_str(),
genesis 1555 DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
genesis 1556 block.vtx.size());
genesis 1557
genesis 1558 PrintWallets(block);
genesis 1559
genesis 1560
genesis 1561 vector<CBlockIndex*>& vNext = mapNext[pindex];
genesis 1562 for (int i = 0; i < vNext.size(); i++)
genesis 1563 {
genesis 1564 if (vNext[i]->pnext)
genesis 1565 {
genesis 1566 swap(vNext[0], vNext[i]);
genesis 1567 break;
genesis 1568 }
genesis 1569 }
genesis 1570
genesis 1571
genesis 1572 for (int i = 0; i < vNext.size(); i++)
genesis 1573 vStack.push_back(make_pair(nCol+i, vNext[i]));
genesis 1574 }
genesis 1575 }
genesis 1576
genesis 1577
genesis 1578
genesis 1579
genesis 1580
bitcoin-asciilife... 1581
genesis 1582
genesis 1583
genesis 1584 string GetWarnings(string strFor)
genesis 1585 {
genesis 1586 int nPriority = 0;
genesis 1587 string strStatusBar;
genesis 1588 string strRPC;
genesis 1589 if (GetBoolArg("-testsafemode"))
genesis 1590 strRPC = "test";
genesis 1591
genesis 1592
genesis 1593 if (strMiscWarning != "")
genesis 1594 {
genesis 1595 nPriority = 1000;
genesis 1596 strStatusBar = strMiscWarning;
genesis 1597 }
genesis 1598
genesis 1599
genesis 1600 if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
genesis 1601 {
genesis 1602 nPriority = 2000;
genesis 1603 strStatusBar = strRPC = "WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.";
genesis 1604 }
genesis 1605
genesis 1606 if (strFor == "statusbar")
genesis 1607 return strStatusBar;
genesis 1608 else if (strFor == "rpc")
genesis 1609 return strRPC;
genesis 1610 assert(!"GetWarnings() : invalid parameter");
genesis 1611 return "error";
genesis 1612 }
genesis 1613
genesis 1614
genesis 1615
genesis 1616
genesis 1617
genesis 1618
genesis 1619
genesis 1620
genesis 1621 bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
genesis 1622 {
genesis 1623 switch (inv.type)
genesis 1624 {
asciilifeform_tx-... 1625 case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
asciilifeform_orp... 1626 case MSG_BLOCK: return mapBlockIndex.count(inv.hash);
genesis 1627 }
genesis 1628
genesis 1629 return true;
genesis 1630 }
genesis 1631
genesis 1632
genesis 1633
genesis 1634
genesis 1635
genesis 1636
genesis 1637
genesis 1638 unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
genesis 1639
genesis 1640
genesis 1641 bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
genesis 1642 {
genesis 1643 static map<unsigned int, vector<unsigned char> > mapReuseKey;
genesis 1644 RandAddSeedPerfmon();
genesis 1645 if (fDebug) {
genesis 1646 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis 1647 printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());
genesis 1648 }
genesis 1649 if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
genesis 1650 {
genesis 1651 printf("dropmessagestest DROPPING RECV MESSAGE\n");
genesis 1652 return true;
genesis 1653 }
genesis 1654
genesis 1655
genesis 1656
genesis 1657
genesis 1658
genesis 1659 if (strCommand == "version")
genesis 1660 {
genesis 1661
genesis 1662 if (pfrom->nVersion != 0)
genesis 1663 {
genesis 1664 pfrom->Misbehaving(1);
genesis 1665 return false;
genesis 1666 }
genesis 1667
genesis 1668 int64 nTime;
genesis 1669 CAddress addrMe;
genesis 1670 CAddress addrFrom;
genesis 1671 uint64 nNonce = 1;
genesis 1672 vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
genesis 1673 if (pfrom->nVersion == 10300)
genesis 1674 pfrom->nVersion = 300;
genesis 1675 if (pfrom->nVersion >= 106 && !vRecv.empty())
genesis 1676 vRecv >> addrFrom >> nNonce;
genesis 1677 if (pfrom->nVersion >= 106 && !vRecv.empty())
genesis 1678 vRecv >> pfrom->strSubVer;
genesis 1679 if (pfrom->nVersion >= 209 && !vRecv.empty())
genesis 1680 vRecv >> pfrom->nStartingHeight;
genesis 1681
genesis 1682 if (pfrom->nVersion == 0)
genesis 1683 return false;
genesis 1684
genesis 1685
genesis 1686 if (nNonce == nLocalHostNonce && nNonce > 1)
genesis 1687 {
genesis 1688 printf("connected to self at %s, disconnecting\n", pfrom->addr.ToString().c_str());
genesis 1689 pfrom->fDisconnect = true;
genesis 1690 return true;
genesis 1691 }
genesis 1692
genesis 1693
genesis 1694 if (pfrom->fInbound)
genesis 1695 pfrom->PushVersion();
genesis 1696
genesis 1697 pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
genesis 1698
genesis 1699 AddTimeData(pfrom->addr.ip, nTime);
genesis 1700
genesis 1701
genesis 1702 if (pfrom->nVersion >= 209)
genesis 1703 pfrom->PushMessage("verack");
genesis 1704 pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
genesis 1705 if (pfrom->nVersion < 209)
genesis 1706 pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
genesis 1707
genesis 1708 if (!pfrom->fInbound)
genesis 1709 {
genesis 1710
genesis 1711 if (addrLocalHost.IsRoutable() && !fUseProxy)
genesis 1712 {
genesis 1713 CAddress addr(addrLocalHost);
genesis 1714 addr.nTime = GetAdjustedTime();
genesis 1715 pfrom->PushAddress(addr);
genesis 1716 }
genesis 1717
genesis 1718
genesis 1719 if (pfrom->nVersion >= 31402 || mapAddresses.size() < 1000)
genesis 1720 {
genesis 1721 pfrom->PushMessage("getaddr");
genesis 1722 pfrom->fGetAddr = true;
genesis 1723 }
genesis 1724 }
genesis 1725
genesis 1726
genesis 1727 static int nAskedForBlocks;
genesis 1728 if (!pfrom->fClient &&
genesis 1729 (pfrom->nVersion < 32000 || pfrom->nVersion >= 32400) &&
genesis 1730 (nAskedForBlocks < 1 || vNodes.size() <= 1))
genesis 1731 {
genesis 1732 nAskedForBlocks++;
genesis 1733 pfrom->PushGetBlocks(pindexBest, uint256(0));
genesis 1734 }
genesis 1735
genesis 1736 pfrom->fSuccessfullyConnected = true;
genesis 1737
genesis 1738 printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);
genesis 1739
genesis 1740 cPeerBlockCounts.input(pfrom->nStartingHeight);
genesis 1741 }
genesis 1742
genesis 1743
genesis 1744 else if (pfrom->nVersion == 0)
genesis 1745 {
genesis 1746
genesis 1747 pfrom->Misbehaving(1);
genesis 1748 return false;
genesis 1749 }
genesis 1750
genesis 1751
genesis 1752 else if (strCommand == "verack")
genesis 1753 {
genesis 1754 pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
genesis 1755 }
genesis 1756
genesis 1757
genesis 1758 else if (strCommand == "addr")
genesis 1759 {
genesis 1760 vector<CAddress> vAddr;
genesis 1761 vRecv >> vAddr;
genesis 1762
genesis 1763
genesis 1764 if (pfrom->nVersion < 209)
genesis 1765 return true;
genesis 1766 if (pfrom->nVersion < 31402 && mapAddresses.size() > 1000)
genesis 1767 return true;
genesis 1768 if (vAddr.size() > 1000)
genesis 1769 {
genesis 1770 pfrom->Misbehaving(20);
genesis 1771 return error("message addr size() = %d", vAddr.size());
genesis 1772 }
genesis 1773
genesis 1774
genesis 1775 CAddrDB addrDB;
genesis 1776 addrDB.TxnBegin();
genesis 1777 int64 nNow = GetAdjustedTime();
genesis 1778 int64 nSince = nNow - 10 * 60;
genesis 1779 BOOST_FOREACH(CAddress& addr, vAddr)
genesis 1780 {
genesis 1781 if (fShutdown)
genesis 1782 return true;
genesis 1783
genesis 1784 if (!addr.IsIPv4())
genesis 1785 continue;
genesis 1786 if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
genesis 1787 addr.nTime = nNow - 5 * 24 * 60 * 60;
genesis 1788 AddAddress(addr, 2 * 60 * 60, &addrDB);
genesis 1789 pfrom->AddAddressKnown(addr);
genesis 1790 if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
genesis 1791 {
genesis 1792
genesis 1793 CRITICAL_BLOCK(cs_vNodes)
genesis 1794 {
genesis 1795
genesis 1796
genesis 1797 static uint256 hashSalt;
genesis 1798 if (hashSalt == 0)
genesis 1799 RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
genesis 1800 uint256 hashRand = hashSalt ^ (((int64)addr.ip)<<32) ^ ((GetTime()+addr.ip)/(24*60*60));
genesis 1801 hashRand = Hash(BEGIN(hashRand), END(hashRand));
genesis 1802 multimap<uint256, CNode*> mapMix;
genesis 1803 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 1804 {
genesis 1805 if (pnode->nVersion < 31402)
genesis 1806 continue;
genesis 1807 unsigned int nPointer;
genesis 1808 memcpy(&nPointer, &pnode, sizeof(nPointer));
genesis 1809 uint256 hashKey = hashRand ^ nPointer;
genesis 1810 hashKey = Hash(BEGIN(hashKey), END(hashKey));
genesis 1811 mapMix.insert(make_pair(hashKey, pnode));
genesis 1812 }
genesis 1813 int nRelayNodes = 2;
genesis 1814 for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
genesis 1815 ((*mi).second)->PushAddress(addr);
genesis 1816 }
genesis 1817 }
genesis 1818 }
genesis 1819 addrDB.TxnCommit();
genesis 1820 if (vAddr.size() < 1000)
genesis 1821 pfrom->fGetAddr = false;
genesis 1822 }
genesis 1823
genesis 1824
genesis 1825 else if (strCommand == "inv")
genesis 1826 {
genesis 1827 vector<CInv> vInv;
genesis 1828 vRecv >> vInv;
genesis 1829 if (vInv.size() > 50000)
genesis 1830 {
genesis 1831 pfrom->Misbehaving(20);
genesis 1832 return error("message inv size() = %d", vInv.size());
genesis 1833 }
genesis 1834
genesis 1835 CTxDB txdb("r");
genesis 1836 BOOST_FOREACH(const CInv& inv, vInv)
genesis 1837 {
genesis 1838 if (fShutdown)
genesis 1839 return true;
genesis 1840 pfrom->AddInventoryKnown(inv);
genesis 1841
genesis 1842 bool fAlreadyHave = AlreadyHave(txdb, inv);
genesis 1843 if (fDebug)
genesis 1844 printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
genesis 1845
genesis 1846 if (!fAlreadyHave)
genesis 1847 pfrom->AskFor(inv);
genesis 1848
genesis 1849
genesis 1850 Inventory(inv.hash);
genesis 1851 }
genesis 1852 }
genesis 1853
genesis 1854
genesis 1855 else if (strCommand == "getdata")
genesis 1856 {
genesis 1857 vector<CInv> vInv;
genesis 1858 vRecv >> vInv;
genesis 1859 if (vInv.size() > 50000)
genesis 1860 {
genesis 1861 pfrom->Misbehaving(20);
genesis 1862 return error("message getdata size() = %d", vInv.size());
genesis 1863 }
genesis 1864
genesis 1865 BOOST_FOREACH(const CInv& inv, vInv)
genesis 1866 {
genesis 1867 if (fShutdown)
genesis 1868 return true;
genesis 1869 printf("received getdata for: %s\n", inv.ToString().c_str());
genesis 1870
genesis 1871 if (inv.type == MSG_BLOCK)
genesis 1872 {
genesis 1873
genesis 1874 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
genesis 1875 if (mi != mapBlockIndex.end())
genesis 1876 {
genesis 1877 CBlock block;
genesis 1878 block.ReadFromDisk((*mi).second);
genesis 1879 pfrom->PushMessage("block", block);
genesis 1880
genesis 1881
genesis 1882 if (inv.hash == pfrom->hashContinue)
genesis 1883 {
genesis 1884
genesis 1885
genesis 1886
genesis 1887 vector<CInv> vInv;
genesis 1888 vInv.push_back(CInv(MSG_BLOCK, hashBestChain));
genesis 1889 pfrom->PushMessage("inv", vInv);
genesis 1890 pfrom->hashContinue = 0;
genesis 1891 }
genesis 1892 }
genesis 1893 }
genesis 1894 else if (inv.IsKnownType())
genesis 1895 {
genesis 1896
genesis 1897 CRITICAL_BLOCK(cs_mapRelay)
genesis 1898 {
genesis 1899 map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
genesis 1900 if (mi != mapRelay.end())
genesis 1901 pfrom->PushMessage(inv.GetCommand(), (*mi).second);
genesis 1902 }
genesis 1903 }
genesis 1904
genesis 1905
genesis 1906 Inventory(inv.hash);
genesis 1907 }
genesis 1908 }
genesis 1909
genesis 1910
genesis 1911 else if (strCommand == "getblocks")
genesis 1912 {
genesis 1913 CBlockLocator locator;
genesis 1914 uint256 hashStop;
genesis 1915 vRecv >> locator >> hashStop;
genesis 1916
genesis 1917
genesis 1918 CBlockIndex* pindex = locator.GetBlockIndex();
genesis 1919
genesis 1920
genesis 1921 if (pindex)
genesis 1922 pindex = pindex->pnext;
genesis 1923 int nLimit = 500 + locator.GetDistanceBack();
genesis 1924 unsigned int nBytes = 0;
genesis 1925 printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
genesis 1926 for (; pindex; pindex = pindex->pnext)
genesis 1927 {
genesis 1928 if (pindex->GetBlockHash() == hashStop)
genesis 1929 {
genesis 1930 printf(" getblocks stopping at %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes);
genesis 1931 break;
genesis 1932 }
genesis 1933 pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
genesis 1934 CBlock block;
genesis 1935 block.ReadFromDisk(pindex, true);
genesis 1936 nBytes += block.GetSerializeSize(SER_NETWORK);
genesis 1937 if (--nLimit <= 0 || nBytes >= SendBufferSize()/2)
genesis 1938 {
genesis 1939
genesis 1940
genesis 1941 printf(" getblocks stopping at limit %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes);
genesis 1942 pfrom->hashContinue = pindex->GetBlockHash();
genesis 1943 break;
genesis 1944 }
genesis 1945 }
genesis 1946 }
genesis 1947
genesis 1948
genesis 1949 else if (strCommand == "getheaders")
genesis 1950 {
genesis 1951 CBlockLocator locator;
genesis 1952 uint256 hashStop;
genesis 1953 vRecv >> locator >> hashStop;
genesis 1954
genesis 1955 CBlockIndex* pindex = NULL;
genesis 1956 if (locator.IsNull())
genesis 1957 {
genesis 1958
genesis 1959 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashStop);
genesis 1960 if (mi == mapBlockIndex.end())
genesis 1961 return true;
genesis 1962 pindex = (*mi).second;
genesis 1963 }
genesis 1964 else
genesis 1965 {
genesis 1966
genesis 1967 pindex = locator.GetBlockIndex();
genesis 1968 if (pindex)
genesis 1969 pindex = pindex->pnext;
genesis 1970 }
genesis 1971
genesis 1972 vector<CBlock> vHeaders;
genesis 1973 int nLimit = 2000 + locator.GetDistanceBack();
genesis 1974 printf("getheaders %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
genesis 1975 for (; pindex; pindex = pindex->pnext)
genesis 1976 {
genesis 1977 vHeaders.push_back(pindex->GetBlockHeader());
genesis 1978 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
genesis 1979 break;
genesis 1980 }
genesis 1981 pfrom->PushMessage("headers", vHeaders);
genesis 1982 }
genesis 1983
genesis 1984
genesis 1985 else if (strCommand == "tx")
genesis 1986 {
genesis 1987 vector<uint256> vWorkQueue;
genesis 1988 CDataStream vMsg(vRecv);
genesis 1989 CTransaction tx;
genesis 1990 vRecv >> tx;
genesis 1991
genesis 1992 CInv inv(MSG_TX, tx.GetHash());
genesis 1993 pfrom->AddInventoryKnown(inv);
genesis 1994
genesis 1995 bool fMissingInputs = false;
genesis 1996 if (tx.AcceptToMemoryPool(true, &fMissingInputs))
genesis 1997 {
genesis 1998 SyncWithWallets(tx, NULL, true);
genesis 1999 RelayMessage(inv, vMsg);
genesis 2000 mapAlreadyAskedFor.erase(inv);
genesis 2001 vWorkQueue.push_back(inv.hash);
genesis 2002 }
genesis 2003 else if (fMissingInputs)
genesis 2004 {
asciilifeform_tx-... 2005 printf("REJECTED orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
genesis 2006 }
genesis 2007 if (tx.nDoS) pfrom->Misbehaving(tx.nDoS);
genesis 2008 }
genesis 2009
genesis 2010
genesis 2011 else if (strCommand == "block")
genesis 2012 {
genesis 2013 CBlock block;
genesis 2014 vRecv >> block;
genesis 2015
genesis 2016 printf("received block %s\n", block.GetHash().ToString().substr(0,20).c_str());
genesis 2017
genesis 2018
genesis 2019 CInv inv(MSG_BLOCK, block.GetHash());
genesis 2020 pfrom->AddInventoryKnown(inv);
genesis 2021
genesis 2022 if (ProcessBlock(pfrom, &block))
genesis 2023 mapAlreadyAskedFor.erase(inv);
genesis 2024 if (block.nDoS) pfrom->Misbehaving(block.nDoS);
genesis 2025 }
genesis 2026
genesis 2027
genesis 2028 else if (strCommand == "getaddr")
genesis 2029 {
genesis 2030
genesis 2031 pfrom->vAddrToSend.clear();
genesis 2032 int64 nSince = GetAdjustedTime() - 3 * 60 * 60;
genesis 2033 CRITICAL_BLOCK(cs_mapAddresses)
genesis 2034 {
genesis 2035 unsigned int nCount = 0;
genesis 2036 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis 2037 {
genesis 2038 const CAddress& addr = item.second;
genesis 2039 if (addr.nTime > nSince)
genesis 2040 nCount++;
genesis 2041 }
genesis 2042 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis 2043 {
genesis 2044 const CAddress& addr = item.second;
genesis 2045 if (addr.nTime > nSince && GetRand(nCount) < 2500)
genesis 2046 pfrom->PushAddress(addr);
genesis 2047 }
genesis 2048 }
genesis 2049 }
genesis 2050
genesis 2051
genesis 2052 else if (strCommand == "checkorder")
genesis 2053 {
genesis 2054 uint256 hashReply;
genesis 2055 vRecv >> hashReply;
genesis 2056
genesis 2057 if (!GetBoolArg("-allowreceivebyip"))
genesis 2058 {
genesis 2059 pfrom->PushMessage("reply", hashReply, (int)2, string(""));
genesis 2060 return true;
genesis 2061 }
genesis 2062
genesis 2063 CWalletTx order;
genesis 2064 vRecv >> order;
genesis 2065
genesis 2066
genesis 2067
genesis 2068
genesis 2069 if (!mapReuseKey.count(pfrom->addr.ip))
genesis 2070 pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr.ip], true);
genesis 2071
genesis 2072
genesis 2073 CScript scriptPubKey;
genesis 2074 scriptPubKey << mapReuseKey[pfrom->addr.ip] << OP_CHECKSIG;
genesis 2075 pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey);
genesis 2076 }
genesis 2077
genesis 2078
genesis 2079 else if (strCommand == "reply")
genesis 2080 {
genesis 2081 uint256 hashReply;
genesis 2082 vRecv >> hashReply;
genesis 2083
genesis 2084 CRequestTracker tracker;
genesis 2085 CRITICAL_BLOCK(pfrom->cs_mapRequests)
genesis 2086 {
genesis 2087 map<uint256, CRequestTracker>::iterator mi = pfrom->mapRequests.find(hashReply);
genesis 2088 if (mi != pfrom->mapRequests.end())
genesis 2089 {
genesis 2090 tracker = (*mi).second;
genesis 2091 pfrom->mapRequests.erase(mi);
genesis 2092 }
genesis 2093 }
genesis 2094 if (!tracker.IsNull())
genesis 2095 tracker.fn(tracker.param1, vRecv);
genesis 2096 }
genesis 2097
genesis 2098
genesis 2099 else if (strCommand == "ping")
genesis 2100 {
genesis 2101 }
genesis 2102
genesis 2103
genesis 2104 else
genesis 2105 {
genesis 2106
genesis 2107 }
genesis 2108
genesis 2109
genesis 2110
genesis 2111 if (pfrom->fNetworkNode)
genesis 2112 if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")
genesis 2113 AddressCurrentlyConnected(pfrom->addr);
genesis 2114
genesis 2115
genesis 2116 return true;
genesis 2117 }
genesis 2118
genesis 2119 bool ProcessMessages(CNode* pfrom)
genesis 2120 {
genesis 2121 CDataStream& vRecv = pfrom->vRecv;
genesis 2122 if (vRecv.empty())
genesis 2123 return true;
genesis 2124
genesis 2125
genesis 2126
genesis 2127
genesis 2128
genesis 2129
genesis 2130
genesis 2131
genesis 2132
genesis 2133
genesis 2134
genesis 2135
genesis 2136 loop
genesis 2137 {
genesis 2138
genesis 2139 CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
genesis 2140 int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
genesis 2141 if (vRecv.end() - pstart < nHeaderSize)
genesis 2142 {
genesis 2143 if (vRecv.size() > nHeaderSize)
genesis 2144 {
genesis 2145 printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
genesis 2146 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
genesis 2147 }
genesis 2148 break;
genesis 2149 }
genesis 2150 if (pstart - vRecv.begin() > 0)
genesis 2151 printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin());
genesis 2152 vRecv.erase(vRecv.begin(), pstart);
genesis 2153
genesis 2154
genesis 2155 vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);
genesis 2156 CMessageHeader hdr;
genesis 2157 vRecv >> hdr;
genesis 2158 if (!hdr.IsValid())
genesis 2159 {
genesis 2160 printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
genesis 2161 continue;
genesis 2162 }
genesis 2163 string strCommand = hdr.GetCommand();
genesis 2164
genesis 2165
genesis 2166 unsigned int nMessageSize = hdr.nMessageSize;
genesis 2167 if (nMessageSize > MAX_SIZE)
genesis 2168 {
genesis 2169 printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);
genesis 2170 continue;
genesis 2171 }
genesis 2172 if (nMessageSize > vRecv.size())
genesis 2173 {
genesis 2174
genesis 2175 vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
genesis 2176 break;
genesis 2177 }
genesis 2178
genesis 2179
genesis 2180 if (vRecv.GetVersion() >= 209)
genesis 2181 {
genesis 2182 uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
genesis 2183 unsigned int nChecksum = 0;
genesis 2184 memcpy(&nChecksum, &hash, sizeof(nChecksum));
genesis 2185 if (nChecksum != hdr.nChecksum)
genesis 2186 {
genesis 2187 printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
genesis 2188 strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
genesis 2189 continue;
genesis 2190 }
genesis 2191 }
genesis 2192
genesis 2193
genesis 2194 CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
genesis 2195 vRecv.ignore(nMessageSize);
genesis 2196
genesis 2197
genesis 2198 bool fRet = false;
genesis 2199 try
genesis 2200 {
genesis 2201 CRITICAL_BLOCK(cs_main)
genesis 2202 fRet = ProcessMessage(pfrom, strCommand, vMsg);
genesis 2203 if (fShutdown)
genesis 2204 return true;
genesis 2205 }
genesis 2206 catch (std::ios_base::failure& e)
genesis 2207 {
genesis 2208 if (strstr(e.what(), "end of data"))
genesis 2209 {
genesis 2210
genesis 2211 printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
genesis 2212 }
genesis 2213 else if (strstr(e.what(), "size too large"))
genesis 2214 {
genesis 2215
genesis 2216 printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
genesis 2217 }
genesis 2218 else
genesis 2219 {
genesis 2220 PrintExceptionContinue(&e, "ProcessMessage()");
genesis 2221 }
genesis 2222 }
genesis 2223 catch (std::exception& e) {
genesis 2224 PrintExceptionContinue(&e, "ProcessMessage()");
genesis 2225 } catch (...) {
genesis 2226 PrintExceptionContinue(NULL, "ProcessMessage()");
genesis 2227 }
genesis 2228
genesis 2229 if (!fRet)
genesis 2230 printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
genesis 2231 }
genesis 2232
genesis 2233 vRecv.Compact();
genesis 2234 return true;
genesis 2235 }
genesis 2236
genesis 2237
genesis 2238 bool SendMessages(CNode* pto, bool fSendTrickle)
genesis 2239 {
genesis 2240 CRITICAL_BLOCK(cs_main)
genesis 2241 {
genesis 2242
genesis 2243 if (pto->nVersion == 0)
genesis 2244 return true;
genesis 2245
genesis 2246
genesis 2247 if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty())
genesis 2248 pto->PushMessage("ping");
genesis 2249
genesis 2250
genesis 2251 ResendWalletTransactions();
genesis 2252
genesis 2253
genesis 2254 static int64 nLastRebroadcast;
genesis 2255 if (GetTime() - nLastRebroadcast > 24 * 60 * 60)
genesis 2256 {
genesis 2257 nLastRebroadcast = GetTime();
genesis 2258 CRITICAL_BLOCK(cs_vNodes)
genesis 2259 {
genesis 2260 BOOST_FOREACH(CNode* pnode, vNodes)
genesis 2261 {
genesis 2262
genesis 2263 pnode->setAddrKnown.clear();
genesis 2264
genesis 2265
genesis 2266 if (addrLocalHost.IsRoutable() && !fUseProxy)
genesis 2267 {
genesis 2268 CAddress addr(addrLocalHost);
genesis 2269 addr.nTime = GetAdjustedTime();
genesis 2270 pnode->PushAddress(addr);
genesis 2271 }
genesis 2272 }
genesis 2273 }
genesis 2274 }
genesis 2275
genesis 2276
genesis 2277 static int64 nLastClear;
genesis 2278 if (nLastClear == 0)
genesis 2279 nLastClear = GetTime();
genesis 2280 if (GetTime() - nLastClear > 10 * 60 && vNodes.size() >= 3)
genesis 2281 {
genesis 2282 nLastClear = GetTime();
genesis 2283 CRITICAL_BLOCK(cs_mapAddresses)
genesis 2284 {
genesis 2285 CAddrDB addrdb;
genesis 2286 int64 nSince = GetAdjustedTime() - 14 * 24 * 60 * 60;
genesis 2287 for (map<vector<unsigned char>, CAddress>::iterator mi = mapAddresses.begin();
genesis 2288 mi != mapAddresses.end();)
genesis 2289 {
genesis 2290 const CAddress& addr = (*mi).second;
genesis 2291 if (addr.nTime < nSince)
genesis 2292 {
genesis 2293 if (mapAddresses.size() < 1000 || GetTime() > nLastClear + 20)
genesis 2294 break;
genesis 2295 addrdb.EraseAddress(addr);
genesis 2296 mapAddresses.erase(mi++);
genesis 2297 }
genesis 2298 else
genesis 2299 mi++;
genesis 2300 }
genesis 2301 }
genesis 2302 }
genesis 2303
genesis 2304
genesis 2305
genesis 2306
genesis 2307
genesis 2308 if (fSendTrickle)
genesis 2309 {
genesis 2310 vector<CAddress> vAddr;
genesis 2311 vAddr.reserve(pto->vAddrToSend.size());
genesis 2312 BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
genesis 2313 {
genesis 2314
genesis 2315 if (pto->setAddrKnown.insert(addr).second)
genesis 2316 {
genesis 2317 vAddr.push_back(addr);
genesis 2318
genesis 2319 if (vAddr.size() >= 1000)
genesis 2320 {
genesis 2321 pto->PushMessage("addr", vAddr);
genesis 2322 vAddr.clear();
genesis 2323 }
genesis 2324 }
genesis 2325 }
genesis 2326 pto->vAddrToSend.clear();
genesis 2327 if (!vAddr.empty())
genesis 2328 pto->PushMessage("addr", vAddr);
genesis 2329 }
genesis 2330
genesis 2331
genesis 2332
genesis 2333
genesis 2334
genesis 2335 vector<CInv> vInv;
genesis 2336 vector<CInv> vInvWait;
genesis 2337 CRITICAL_BLOCK(pto->cs_inventory)
genesis 2338 {
genesis 2339 vInv.reserve(pto->vInventoryToSend.size());
genesis 2340 vInvWait.reserve(pto->vInventoryToSend.size());
genesis 2341 BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
genesis 2342 {
genesis 2343 if (pto->setInventoryKnown.count(inv))
genesis 2344 continue;
genesis 2345
genesis 2346
genesis 2347 if (inv.type == MSG_TX && !fSendTrickle)
genesis 2348 {
genesis 2349
genesis 2350 static uint256 hashSalt;
genesis 2351 if (hashSalt == 0)
genesis 2352 RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
genesis 2353 uint256 hashRand = inv.hash ^ hashSalt;
genesis 2354 hashRand = Hash(BEGIN(hashRand), END(hashRand));
genesis 2355 bool fTrickleWait = ((hashRand & 3) != 0);
genesis 2356
genesis 2357
genesis 2358 if (!fTrickleWait)
genesis 2359 {
genesis 2360 CWalletTx wtx;
genesis 2361 if (GetTransaction(inv.hash, wtx))
genesis 2362 if (wtx.fFromMe)
genesis 2363 fTrickleWait = true;
genesis 2364 }
genesis 2365
genesis 2366 if (fTrickleWait)
genesis 2367 {
genesis 2368 vInvWait.push_back(inv);
genesis 2369 continue;
genesis 2370 }
genesis 2371 }
genesis 2372
genesis 2373
genesis 2374 if (pto->setInventoryKnown.insert(inv).second)
genesis 2375 {
genesis 2376 vInv.push_back(inv);
genesis 2377 if (vInv.size() >= 1000)
genesis 2378 {
genesis 2379 pto->PushMessage("inv", vInv);
genesis 2380 vInv.clear();
genesis 2381 }
genesis 2382 }
genesis 2383 }
genesis 2384 pto->vInventoryToSend = vInvWait;
genesis 2385 }
genesis 2386 if (!vInv.empty())
genesis 2387 pto->PushMessage("inv", vInv);
genesis 2388
genesis 2389
genesis 2390
genesis 2391
genesis 2392
genesis 2393 vector<CInv> vGetData;
genesis 2394 int64 nNow = GetTime() * 1000000;
genesis 2395 CTxDB txdb("r");
genesis 2396 while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
genesis 2397 {
genesis 2398 const CInv& inv = (*pto->mapAskFor.begin()).second;
genesis 2399 if (!AlreadyHave(txdb, inv))
genesis 2400 {
genesis 2401 printf("sending getdata: %s\n", inv.ToString().c_str());
genesis 2402 vGetData.push_back(inv);
genesis 2403 if (vGetData.size() >= 1000)
genesis 2404 {
genesis 2405 pto->PushMessage("getdata", vGetData);
genesis 2406 vGetData.clear();
genesis 2407 }
genesis 2408 }
genesis 2409 mapAlreadyAskedFor[inv] = nNow;
genesis 2410 pto->mapAskFor.erase(pto->mapAskFor.begin());
genesis 2411 }
genesis 2412 if (!vGetData.empty())
genesis 2413 pto->PushMessage("getdata", vGetData);
genesis 2414
genesis 2415 }
genesis 2416 return true;
genesis 2417 }
genesis 2418
genesis 2419
genesis 2420
genesis 2421
genesis 2422
genesis 2423
genesis 2424
genesis 2425
genesis 2426
genesis 2427
genesis 2428
genesis 2429
genesis 2430
genesis 2431
genesis 2432
genesis 2433
genesis 2434
genesis 2435
genesis 2436
genesis 2437 int static FormatHashBlocks(void* pbuffer, unsigned int len)
genesis 2438 {
genesis 2439 unsigned char* pdata = (unsigned char*)pbuffer;
genesis 2440 unsigned int blocks = 1 + ((len + 8) / 64);
genesis 2441 unsigned char* pend = pdata + 64 * blocks;
genesis 2442 memset(pdata + len, 0, 64 * blocks - len);
genesis 2443 pdata[len] = 0x80;
genesis 2444 unsigned int bits = len * 8;
genesis 2445 pend[-1] = (bits >> 0) & 0xff;
genesis 2446 pend[-2] = (bits >> 8) & 0xff;
genesis 2447 pend[-3] = (bits >> 16) & 0xff;
genesis 2448 pend[-4] = (bits >> 24) & 0xff;
genesis 2449 return blocks;
genesis 2450 }
genesis 2451
genesis 2452 static const unsigned int pSHA256InitState[8] =
genesis 2453 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
genesis 2454
genesis 2455 void SHA256Transform(void* pstate, void* pinput, const void* pinit)
genesis 2456 {
genesis 2457 SHA256_CTX ctx;
genesis 2458 unsigned char data[64];
genesis 2459
genesis 2460 SHA256_Init(&ctx);
genesis 2461
genesis 2462 for (int i = 0; i < 16; i++)
genesis 2463 ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
genesis 2464
genesis 2465 for (int i = 0; i < 8; i++)
genesis 2466 ctx.h[i] = ((uint32_t*)pinit)[i];
genesis 2467
genesis 2468 SHA256_Update(&ctx, data, sizeof(data));
genesis 2469 for (int i = 0; i < 8; i++)
genesis 2470 ((uint32_t*)pstate)[i] = ctx.h[i];
genesis 2471 }
genesis 2472
genesis 2473
genesis 2474
genesis 2475
genesis 2476
genesis 2477
genesis 2478
genesis 2479
genesis 2480 unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
genesis 2481 {
genesis 2482 unsigned int& nNonce = *(unsigned int*)(pdata + 12);
genesis 2483 for (;;)
genesis 2484 {
genesis 2485
genesis 2486
genesis 2487
genesis 2488 nNonce++;
genesis 2489 SHA256Transform(phash1, pdata, pmidstate);
genesis 2490 SHA256Transform(phash, phash1, pSHA256InitState);
genesis 2491
genesis 2492
genesis 2493
genesis 2494 if (((unsigned short*)phash)[14] == 0)
genesis 2495 return nNonce;
genesis 2496
genesis 2497
genesis 2498 if ((nNonce & 0xffff) == 0)
genesis 2499 {
genesis 2500 nHashesDone = 0xffff+1;
genesis 2501 return -1;
genesis 2502 }
genesis 2503 }
genesis 2504 }
genesis 2505
genesis 2506
genesis 2507 class COrphan
genesis 2508 {
genesis 2509 public:
genesis 2510 CTransaction* ptx;
genesis 2511 set<uint256> setDependsOn;
genesis 2512 double dPriority;
genesis 2513
genesis 2514 COrphan(CTransaction* ptxIn)
genesis 2515 {
genesis 2516 ptx = ptxIn;
genesis 2517 dPriority = 0;
genesis 2518 }
genesis 2519
genesis 2520 void print() const
genesis 2521 {
genesis 2522 printf("COrphan(hash=%s, dPriority=%.1f)\n", ptx->GetHash().ToString().substr(0,10).c_str(), dPriority);
genesis 2523 BOOST_FOREACH(uint256 hash, setDependsOn)
genesis 2524 printf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str());
genesis 2525 }
genesis 2526 };
genesis 2527
genesis 2528
genesis 2529 CBlock* CreateNewBlock(CReserveKey& reservekey)
genesis 2530 {
genesis 2531 CBlockIndex* pindexPrev = pindexBest;
genesis 2532
genesis 2533
genesis 2534 auto_ptr<CBlock> pblock(new CBlock());
genesis 2535 if (!pblock.get())
genesis 2536 return NULL;
genesis 2537
genesis 2538
genesis 2539 CTransaction txNew;
genesis 2540 txNew.vin.resize(1);
genesis 2541 txNew.vin[0].prevout.SetNull();
genesis 2542 txNew.vout.resize(1);
genesis 2543 txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
genesis 2544
genesis 2545
genesis 2546 pblock->vtx.push_back(txNew);
genesis 2547
genesis 2548
genesis 2549 int64 nFees = 0;
genesis 2550 CRITICAL_BLOCK(cs_main)
genesis 2551 CRITICAL_BLOCK(cs_mapTransactions)
genesis 2552 {
genesis 2553 CTxDB txdb("r");
genesis 2554
genesis 2555
genesis 2556 list<COrphan> vOrphan;
genesis 2557 map<uint256, vector<COrphan*> > mapDependers;
genesis 2558 multimap<double, CTransaction*> mapPriority;
genesis 2559 for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi)
genesis 2560 {
genesis 2561 CTransaction& tx = (*mi).second;
genesis 2562 if (tx.IsCoinBase() || !tx.IsFinal())
genesis 2563 continue;
genesis 2564
genesis 2565 COrphan* porphan = NULL;
genesis 2566 double dPriority = 0;
genesis 2567 BOOST_FOREACH(const CTxIn& txin, tx.vin)
genesis 2568 {
genesis 2569
genesis 2570 CTransaction txPrev;
genesis 2571 CTxIndex txindex;
genesis 2572 if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
genesis 2573 {
genesis 2574
genesis 2575 if (!porphan)
genesis 2576 {
genesis 2577
genesis 2578 vOrphan.push_back(COrphan(&tx));
genesis 2579 porphan = &vOrphan.back();
genesis 2580 }
genesis 2581 mapDependers[txin.prevout.hash].push_back(porphan);
genesis 2582 porphan->setDependsOn.insert(txin.prevout.hash);
genesis 2583 continue;
genesis 2584 }
genesis 2585 int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
genesis 2586
genesis 2587
genesis 2588 int nConf = txindex.GetDepthInMainChain();
genesis 2589
genesis 2590 dPriority += (double)nValueIn * nConf;
genesis 2591
genesis 2592 if (fDebug && GetBoolArg("-printpriority"))
genesis 2593 printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
genesis 2594 }
genesis 2595
genesis 2596
genesis 2597 dPriority /= ::GetSerializeSize(tx, SER_NETWORK);
genesis 2598
genesis 2599 if (porphan)
genesis 2600 porphan->dPriority = dPriority;
genesis 2601 else
genesis 2602 mapPriority.insert(make_pair(-dPriority, &(*mi).second));
genesis 2603
genesis 2604 if (fDebug && GetBoolArg("-printpriority"))
genesis 2605 {
genesis 2606 printf("priority %-20.1f %s\n%s", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str());
genesis 2607 if (porphan)
genesis 2608 porphan->print();
genesis 2609 printf("\n");
genesis 2610 }
genesis 2611 }
genesis 2612
genesis 2613
genesis 2614 map<uint256, CTxIndex> mapTestPool;
genesis 2615 uint64 nBlockSize = 1000;
genesis 2616 int nBlockSigOps = 100;
genesis 2617 while (!mapPriority.empty())
genesis 2618 {
genesis 2619
genesis 2620 double dPriority = -(*mapPriority.begin()).first;
genesis 2621 CTransaction& tx = *(*mapPriority.begin()).second;
genesis 2622 mapPriority.erase(mapPriority.begin());
genesis 2623
genesis 2624
genesis 2625 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
genesis 2626 if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
genesis 2627 continue;
genesis 2628 int nTxSigOps = tx.GetSigOpCount();
genesis 2629 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
genesis 2630 continue;
genesis 2631
genesis 2632
genesis 2633 bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority));
genesis 2634 int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree);
genesis 2635
genesis 2636
genesis 2637
genesis 2638 map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
genesis 2639 bool fInvalid;
genesis 2640 if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee, fInvalid))
genesis 2641 continue;
genesis 2642 swap(mapTestPool, mapTestPoolTmp);
genesis 2643
genesis 2644
genesis 2645 pblock->vtx.push_back(tx);
genesis 2646 nBlockSize += nTxSize;
genesis 2647 nBlockSigOps += nTxSigOps;
genesis 2648
genesis 2649
genesis 2650 uint256 hash = tx.GetHash();
genesis 2651 if (mapDependers.count(hash))
genesis 2652 {
genesis 2653 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
genesis 2654 {
genesis 2655 if (!porphan->setDependsOn.empty())
genesis 2656 {
genesis 2657 porphan->setDependsOn.erase(hash);
genesis 2658 if (porphan->setDependsOn.empty())
genesis 2659 mapPriority.insert(make_pair(-porphan->dPriority, porphan->ptx));
genesis 2660 }
genesis 2661 }
genesis 2662 }
genesis 2663 }
genesis 2664 }
genesis 2665 pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
genesis 2666
genesis 2667
genesis 2668 pblock->hashPrevBlock = pindexPrev->GetBlockHash();
genesis 2669 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
genesis 2670 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
genesis 2671 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock.get());
genesis 2672 pblock->nNonce = 0;
genesis 2673
genesis 2674 return pblock.release();
genesis 2675 }
genesis 2676
genesis 2677
genesis 2678 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
genesis 2679 {
genesis 2680
genesis 2681 static uint256 hashPrevBlock;
genesis 2682 if (hashPrevBlock != pblock->hashPrevBlock)
genesis 2683 {
genesis 2684 nExtraNonce = 0;
genesis 2685 hashPrevBlock = pblock->hashPrevBlock;
genesis 2686 }
genesis 2687 ++nExtraNonce;
genesis 2688 pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nTime << CBigNum(nExtraNonce);
genesis 2689 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
genesis 2690 }
genesis 2691
genesis 2692
genesis 2693 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
genesis 2694 {
genesis 2695
genesis 2696
genesis 2697
genesis 2698 struct
genesis 2699 {
genesis 2700 struct unnamed2
genesis 2701 {
genesis 2702 int nVersion;
genesis 2703 uint256 hashPrevBlock;
genesis 2704 uint256 hashMerkleRoot;
genesis 2705 unsigned int nTime;
genesis 2706 unsigned int nBits;
genesis 2707 unsigned int nNonce;
genesis 2708 }
genesis 2709 block;
genesis 2710 unsigned char pchPadding0[64];
genesis 2711 uint256 hash1;
genesis 2712 unsigned char pchPadding1[64];
genesis 2713 }
genesis 2714 tmp;
genesis 2715 memset(&tmp, 0, sizeof(tmp));
genesis 2716
genesis 2717 tmp.block.nVersion = pblock->nVersion;
genesis 2718 tmp.block.hashPrevBlock = pblock->hashPrevBlock;
genesis 2719 tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
genesis 2720 tmp.block.nTime = pblock->nTime;
genesis 2721 tmp.block.nBits = pblock->nBits;
genesis 2722 tmp.block.nNonce = pblock->nNonce;
genesis 2723
genesis 2724 FormatHashBlocks(&tmp.block, sizeof(tmp.block));
genesis 2725 FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
genesis 2726
genesis 2727
genesis 2728 for (int i = 0; i < sizeof(tmp)/4; i++)
genesis 2729 ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
genesis 2730
genesis 2731
genesis 2732 SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
genesis 2733
genesis 2734 memcpy(pdata, &tmp.block, 128);
genesis 2735 memcpy(phash1, &tmp.hash1, 64);
genesis 2736 }
genesis 2737
genesis 2738
genesis 2739 bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
genesis 2740 {
genesis 2741 uint256 hash = pblock->GetHash();
genesis 2742 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
genesis 2743
genesis 2744 if (hash > hashTarget)
genesis 2745 return false;
genesis 2746
genesis 2747
genesis 2748 printf("BitcoinMiner:\n");
genesis 2749 printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
genesis 2750 pblock->print();
genesis 2751 printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());
genesis 2752 printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
genesis 2753
genesis 2754
genesis 2755 CRITICAL_BLOCK(cs_main)
genesis 2756 {
genesis 2757 if (pblock->hashPrevBlock != hashBestChain)
genesis 2758 return error("BitcoinMiner : generated block is stale");
genesis 2759
genesis 2760
genesis 2761 reservekey.KeepKey();
genesis 2762
genesis 2763
genesis 2764 CRITICAL_BLOCK(wallet.cs_wallet)
genesis 2765 wallet.mapRequestCount[pblock->GetHash()] = 0;
genesis 2766
genesis 2767
genesis 2768 if (!ProcessBlock(NULL, pblock))
genesis 2769 return error("BitcoinMiner : ProcessBlock, block not accepted");
genesis 2770 }
genesis 2771
genesis 2772 return true;
genesis 2773 }
genesis 2774
genesis 2775 void static ThreadBitcoinMiner(void* parg);
genesis 2776
genesis 2777 void static BitcoinMiner(CWallet *pwallet)
genesis 2778 {
genesis 2779 printf("BitcoinMiner started\n");
genesis 2780 SetThreadPriority(THREAD_PRIORITY_LOWEST);
genesis 2781
genesis 2782
genesis 2783 CReserveKey reservekey(pwallet);
genesis 2784 unsigned int nExtraNonce = 0;
genesis 2785
genesis 2786 while (fGenerateBitcoins)
genesis 2787 {
genesis 2788 if (AffinityBugWorkaround(ThreadBitcoinMiner))
genesis 2789 return;
genesis 2790 if (fShutdown)
genesis 2791 return;
genesis 2792 while (vNodes.empty() || IsInitialBlockDownload())
genesis 2793 {
genesis 2794 Sleep(1000);
genesis 2795 if (fShutdown)
genesis 2796 return;
genesis 2797 if (!fGenerateBitcoins)
genesis 2798 return;
genesis 2799 }
genesis 2800
genesis 2801
genesis 2802
genesis 2803
genesis 2804
genesis 2805 unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
genesis 2806 CBlockIndex* pindexPrev = pindexBest;
genesis 2807
genesis 2808 auto_ptr<CBlock> pblock(CreateNewBlock(reservekey));
genesis 2809 if (!pblock.get())
genesis 2810 return;
genesis 2811 IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce);
genesis 2812
genesis 2813 printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
genesis 2814
genesis 2815
genesis 2816
genesis 2817
genesis 2818
genesis 2819 char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
genesis 2820 char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
genesis 2821 char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf);
genesis 2822
genesis 2823 FormatHashBuffers(pblock.get(), pmidstate, pdata, phash1);
genesis 2824
genesis 2825 unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
genesis 2826 unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
genesis 2827
genesis 2828
genesis 2829
genesis 2830
genesis 2831
genesis 2832 int64 nStart = GetTime();
genesis 2833 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
genesis 2834 uint256 hashbuf[2];
genesis 2835 uint256& hash = *alignup<16>(hashbuf);
genesis 2836 loop
genesis 2837 {
genesis 2838 unsigned int nHashesDone = 0;
genesis 2839 unsigned int nNonceFound;
genesis 2840
genesis 2841
genesis 2842 nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
genesis 2843 (char*)&hash, nHashesDone);
genesis 2844
genesis 2845
genesis 2846 if (nNonceFound != -1)
genesis 2847 {
genesis 2848 for (int i = 0; i < sizeof(hash)/4; i++)
genesis 2849 ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);
genesis 2850
genesis 2851 if (hash <= hashTarget)
genesis 2852 {
genesis 2853
genesis 2854 pblock->nNonce = ByteReverse(nNonceFound);
genesis 2855 assert(hash == pblock->GetHash());
genesis 2856
genesis 2857 SetThreadPriority(THREAD_PRIORITY_NORMAL);
genesis 2858 CheckWork(pblock.get(), *pwalletMain, reservekey);
genesis 2859 SetThreadPriority(THREAD_PRIORITY_LOWEST);
genesis 2860 break;
genesis 2861 }
genesis 2862 }
genesis 2863
genesis 2864
genesis 2865 static int64 nHashCounter;
genesis 2866 if (nHPSTimerStart == 0)
genesis 2867 {
genesis 2868 nHPSTimerStart = GetTimeMillis();
genesis 2869 nHashCounter = 0;
genesis 2870 }
genesis 2871 else
genesis 2872 nHashCounter += nHashesDone;
genesis 2873 if (GetTimeMillis() - nHPSTimerStart > 4000)
genesis 2874 {
genesis 2875 static CCriticalSection cs;
genesis 2876 CRITICAL_BLOCK(cs)
genesis 2877 {
genesis 2878 if (GetTimeMillis() - nHPSTimerStart > 4000)
genesis 2879 {
genesis 2880 dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
genesis 2881 nHPSTimerStart = GetTimeMillis();
genesis 2882 nHashCounter = 0;
genesis 2883 string strStatus = strprintf(" %.0f khash/s", dHashesPerSec/1000.0);
genesis 2884 UIThreadCall(boost::bind(CalledSetStatusBar, strStatus, 0));
genesis 2885 static int64 nLogTime;
genesis 2886 if (GetTime() - nLogTime > 30 * 60)
genesis 2887 {
genesis 2888 nLogTime = GetTime();
genesis 2889 printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());
genesis 2890 printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[3], dHashesPerSec/1000.0);
genesis 2891 }
genesis 2892 }
genesis 2893 }
genesis 2894 }
genesis 2895
genesis 2896
genesis 2897 if (fShutdown)
genesis 2898 return;
genesis 2899 if (!fGenerateBitcoins)
genesis 2900 return;
genesis 2901 if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
genesis 2902 return;
genesis 2903 if (vNodes.empty())
genesis 2904 break;
genesis 2905 if (nBlockNonce >= 0xffff0000)
genesis 2906 break;
genesis 2907 if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
genesis 2908 break;
genesis 2909 if (pindexPrev != pindexBest)
genesis 2910 break;
genesis 2911
genesis 2912
genesis 2913 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
genesis 2914 nBlockTime = ByteReverse(pblock->nTime);
genesis 2915 }
genesis 2916 }
genesis 2917 }
genesis 2918
genesis 2919 void static ThreadBitcoinMiner(void* parg)
genesis 2920 {
genesis 2921 CWallet* pwallet = (CWallet*)parg;
genesis 2922 try
genesis 2923 {
genesis 2924 vnThreadsRunning[3]++;
genesis 2925 BitcoinMiner(pwallet);
genesis 2926 vnThreadsRunning[3]--;
genesis 2927 }
genesis 2928 catch (std::exception& e) {
genesis 2929 vnThreadsRunning[3]--;
genesis 2930 PrintException(&e, "ThreadBitcoinMiner()");
genesis 2931 } catch (...) {
genesis 2932 vnThreadsRunning[3]--;
genesis 2933 PrintException(NULL, "ThreadBitcoinMiner()");
genesis 2934 }
genesis 2935 UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
genesis 2936 nHPSTimerStart = 0;
genesis 2937 if (vnThreadsRunning[3] == 0)
genesis 2938 dHashesPerSec = 0;
genesis 2939 printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
genesis 2940 }
genesis 2941
genesis 2942
genesis 2943 void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
genesis 2944 {
genesis 2945 if (fGenerateBitcoins != fGenerate)
genesis 2946 {
genesis 2947 fGenerateBitcoins = fGenerate;
genesis 2948 WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
genesis 2949 MainFrameRepaint();
genesis 2950 }
genesis 2951 if (fGenerateBitcoins)
genesis 2952 {
genesis 2953 int nProcessors = boost::thread::hardware_concurrency();
genesis 2954 printf("%d processors\n", nProcessors);
genesis 2955 if (nProcessors < 1)
genesis 2956 nProcessors = 1;
genesis 2957 if (fLimitProcessors && nProcessors > nLimitProcessors)
genesis 2958 nProcessors = nLimitProcessors;
genesis 2959 int nAddThreads = nProcessors - vnThreadsRunning[3];
genesis 2960 printf("Starting %d BitcoinMiner threads\n", nAddThreads);
genesis 2961 for (int i = 0; i < nAddThreads; i++)
genesis 2962 {
genesis 2963 if (!CreateThread(ThreadBitcoinMiner, pwallet))
genesis 2964 printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
genesis 2965 Sleep(10);
genesis 2966 }
genesis 2967 }
genesis 2968 }