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