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