genesis 1
genesis 2
genesis 3
genesis 4
genesis 5
genesis 6 #include "headers.h"
genesis 7 #include "db.h"
genesis 8 #include "crypter.h"
genesis 9
genesis 10 using namespace std;
genesis 11
genesis 12
genesis 13
genesis 14
genesis 15
genesis 16
genesis 17
genesis 18 bool CWallet::AddKey(const CKey& key)
genesis 19 {
genesis 20 if (!CCryptoKeyStore::AddKey(key))
genesis 21 return false;
genesis 22 if (!fFileBacked)
genesis 23 return true;
genesis 24 if (!IsCrypted())
genesis 25 return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
genesis 26 return true;
genesis 27 }
genesis 28
genesis 29 bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
genesis 30 {
genesis 31 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
genesis 32 return false;
genesis 33 if (!fFileBacked)
genesis 34 return true;
genesis 35 CRITICAL_BLOCK(cs_wallet)
genesis 36 {
genesis 37 if (pwalletdbEncryption)
genesis 38 return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
genesis 39 else
genesis 40 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
genesis 41 }
genesis 42 return false;
genesis 43 }
genesis 44
genesis 45 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
genesis 46 {
genesis 47 if (!IsLocked())
genesis 48 return false;
genesis 49
genesis 50 CCrypter crypter;
genesis 51 CKeyingMaterial vMasterKey;
genesis 52
genesis 53 CRITICAL_BLOCK(cs_wallet)
genesis 54 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
genesis 55 {
genesis 56 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
genesis 57 return false;
genesis 58 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
genesis 59 return false;
genesis 60 if (CCryptoKeyStore::Unlock(vMasterKey))
genesis 61 return true;
genesis 62 }
genesis 63 return false;
genesis 64 }
genesis 65
genesis 66 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
genesis 67 {
genesis 68 bool fWasLocked = IsLocked();
genesis 69
genesis 70 CRITICAL_BLOCK(cs_wallet)
genesis 71 {
genesis 72 Lock();
genesis 73
genesis 74 CCrypter crypter;
genesis 75 CKeyingMaterial vMasterKey;
genesis 76 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
genesis 77 {
genesis 78 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
genesis 79 return false;
genesis 80 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
genesis 81 return false;
genesis 82 if (CCryptoKeyStore::Unlock(vMasterKey))
genesis 83 {
genesis 84 int64 nStartTime = GetTimeMillis();
genesis 85 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
genesis 86 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
genesis 87
genesis 88 nStartTime = GetTimeMillis();
genesis 89 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
genesis 90 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
genesis 91
genesis 92 if (pMasterKey.second.nDeriveIterations < 25000)
genesis 93 pMasterKey.second.nDeriveIterations = 25000;
genesis 94
polarbeard_better... 95 printf(SINF SWAL "passphrase changed through %i deriving iterations\n", pMasterKey.second.nDeriveIterations);
genesis 96
genesis 97 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
genesis 98 return false;
genesis 99 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
genesis 100 return false;
genesis 101 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
genesis 102 if (fWasLocked)
genesis 103 Lock();
genesis 104 return true;
genesis 105 }
genesis 106 }
genesis 107 }
genesis 108
genesis 109 return false;
genesis 110 }
genesis 111
genesis 112
genesis 113
genesis 114
genesis 115 class CCorruptAddress
genesis 116 {
genesis 117 public:
genesis 118 IMPLEMENT_SERIALIZE
genesis 119 (
genesis 120 if (nType & SER_DISK)
genesis 121 READWRITE(nVersion);
genesis 122 )
genesis 123 };
genesis 124
genesis 125 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
genesis 126 {
genesis 127 if (IsCrypted())
genesis 128 return false;
genesis 129
genesis 130 CKeyingMaterial vMasterKey;
genesis 131 RandAddSeedPerfmon();
genesis 132
genesis 133 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
genesis 134 RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
genesis 135
genesis 136 CMasterKey kMasterKey;
genesis 137
genesis 138 RandAddSeedPerfmon();
genesis 139 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
genesis 140 RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
genesis 141
genesis 142 CCrypter crypter;
genesis 143 int64 nStartTime = GetTimeMillis();
genesis 144 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
genesis 145 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
genesis 146
genesis 147 nStartTime = GetTimeMillis();
genesis 148 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
genesis 149 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
genesis 150
genesis 151 if (kMasterKey.nDeriveIterations < 25000)
genesis 152 kMasterKey.nDeriveIterations = 25000;
genesis 153
polarbeard_better... 154 printf(SINF SWAL "encrypting using %i deriving iterations\n", kMasterKey.nDeriveIterations);
genesis 155
genesis 156 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
genesis 157 return false;
genesis 158 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
genesis 159 return false;
genesis 160
genesis 161 CRITICAL_BLOCK(cs_wallet)
genesis 162 {
genesis 163 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
genesis 164 if (fFileBacked)
genesis 165 {
genesis 166 pwalletdbEncryption = new CWalletDB(strWalletFile);
genesis 167 pwalletdbEncryption->TxnBegin();
genesis 168 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
genesis 169 }
genesis 170
genesis 171 if (!EncryptKeys(vMasterKey))
genesis 172 {
genesis 173 if (fFileBacked)
genesis 174 pwalletdbEncryption->TxnAbort();
genesis 175 exit(1);
genesis 176 }
genesis 177
genesis 178 if (fFileBacked)
genesis 179 {
genesis 180 CCorruptAddress corruptAddress;
genesis 181 pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
genesis 182 if (!pwalletdbEncryption->TxnCommit())
genesis 183 exit(1);
genesis 184
genesis 185 delete pwalletdbEncryption;
genesis 186 pwalletdbEncryption = NULL;
genesis 187 }
genesis 188
genesis 189 Lock();
genesis 190 Unlock(strWalletPassphrase);
genesis 191 NewKeyPool();
genesis 192 Lock();
genesis 193
genesis 194
genesis 195
genesis 196 CDB::Rewrite(strWalletFile);
genesis 197 }
genesis 198
genesis 199 return true;
genesis 200 }
genesis 201
genesis 202 void CWallet::WalletUpdateSpent(const CTransaction &tx)
genesis 203 {
genesis 204
genesis 205
genesis 206
genesis 207 CRITICAL_BLOCK(cs_wallet)
genesis 208 {
genesis 209 BOOST_FOREACH(const CTxIn& txin, tx.vin)
genesis 210 {
genesis 211 map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
genesis 212 if (mi != mapWallet.end())
genesis 213 {
genesis 214 CWalletTx& wtx = (*mi).second;
genesis 215 if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
genesis 216 {
polarbeard_better... 217 printf(SWAR SWAL "found spent %s bitcoin on tx %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
genesis 218 wtx.MarkSpent(txin.prevout.n);
genesis 219 wtx.WriteToDisk();
genesis 220 vWalletUpdated.push_back(txin.prevout.hash);
genesis 221 }
genesis 222 }
genesis 223 }
genesis 224 }
genesis 225 }
genesis 226
genesis 227 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
genesis 228 {
genesis 229 uint256 hash = wtxIn.GetHash();
genesis 230 CRITICAL_BLOCK(cs_wallet)
genesis 231 {
genesis 232
genesis 233 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
genesis 234 CWalletTx& wtx = (*ret.first).second;
genesis 235 wtx.pwallet = this;
genesis 236 bool fInsertedNew = ret.second;
genesis 237 if (fInsertedNew)
genesis 238 wtx.nTimeReceived = GetAdjustedTime();
genesis 239
genesis 240 bool fUpdated = false;
genesis 241 if (!fInsertedNew)
genesis 242 {
genesis 243
genesis 244 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
genesis 245 {
genesis 246 wtx.hashBlock = wtxIn.hashBlock;
genesis 247 fUpdated = true;
genesis 248 }
genesis 249 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
genesis 250 {
genesis 251 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
genesis 252 wtx.nIndex = wtxIn.nIndex;
genesis 253 fUpdated = true;
genesis 254 }
genesis 255 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
genesis 256 {
genesis 257 wtx.fFromMe = wtxIn.fFromMe;
genesis 258 fUpdated = true;
genesis 259 }
genesis 260 fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
genesis 261 }
genesis 262
genesis 263
polarbeard_better... 264 printf(SINF SWAL "adding input from tx %s. (%s)\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new, " : (fUpdated ? "update" : "")));
genesis 265
genesis 266
genesis 267 if (fInsertedNew || fUpdated)
genesis 268 if (!wtx.WriteToDisk())
genesis 269 return false;
genesis 270
genesis 271 CScript scriptDefaultKey;
genesis 272 scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
genesis 273 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis 274 {
genesis 275 if (txout.scriptPubKey == scriptDefaultKey)
genesis 276 {
genesis 277 std::vector<unsigned char> newDefaultKey;
genesis 278 if (GetKeyFromPool(newDefaultKey, false))
genesis 279 {
genesis 280 SetDefaultKey(newDefaultKey);
genesis 281 SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
genesis 282 }
genesis 283 }
genesis 284 }
genesis 285
genesis 286 vWalletUpdated.push_back(hash);
genesis 287
genesis 288
genesis 289 WalletUpdateSpent(wtx);
genesis 290 }
genesis 291
genesis 292
genesis 293 MainFrameRepaint();
genesis 294 return true;
genesis 295 }
genesis 296
genesis 297
genesis 298
genesis 299
genesis 300 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
genesis 301 {
genesis 302 uint256 hash = tx.GetHash();
genesis 303 CRITICAL_BLOCK(cs_wallet)
genesis 304 {
genesis 305 bool fExisted = mapWallet.count(hash);
genesis 306 if (fExisted && !fUpdate) return false;
genesis 307 if (fExisted || IsMine(tx) || IsFromMe(tx))
genesis 308 {
genesis 309 CWalletTx wtx(this,tx);
genesis 310
genesis 311 if (pblock)
genesis 312 wtx.SetMerkleBranch(pblock);
genesis 313 return AddToWallet(wtx);
genesis 314 }
genesis 315 else
genesis 316 WalletUpdateSpent(tx);
genesis 317 }
genesis 318 return false;
genesis 319 }
genesis 320
genesis 321 bool CWallet::EraseFromWallet(uint256 hash)
genesis 322 {
genesis 323 if (!fFileBacked)
genesis 324 return false;
genesis 325 CRITICAL_BLOCK(cs_wallet)
genesis 326 {
genesis 327 if (mapWallet.erase(hash))
genesis 328 CWalletDB(strWalletFile).EraseTx(hash);
genesis 329 }
genesis 330 return true;
genesis 331 }
genesis 332
genesis 333
genesis 334 bool CWallet::IsMine(const CTxIn &txin) const
genesis 335 {
genesis 336 CRITICAL_BLOCK(cs_wallet)
genesis 337 {
genesis 338 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
genesis 339 if (mi != mapWallet.end())
genesis 340 {
genesis 341 const CWalletTx& prev = (*mi).second;
genesis 342 if (txin.prevout.n < prev.vout.size())
genesis 343 if (IsMine(prev.vout[txin.prevout.n]))
genesis 344 return true;
genesis 345 }
genesis 346 }
genesis 347 return false;
genesis 348 }
genesis 349
genesis 350 int64 CWallet::GetDebit(const CTxIn &txin) const
genesis 351 {
genesis 352 CRITICAL_BLOCK(cs_wallet)
genesis 353 {
genesis 354 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
genesis 355 if (mi != mapWallet.end())
genesis 356 {
genesis 357 const CWalletTx& prev = (*mi).second;
genesis 358 if (txin.prevout.n < prev.vout.size())
genesis 359 if (IsMine(prev.vout[txin.prevout.n]))
genesis 360 return prev.vout[txin.prevout.n].nValue;
genesis 361 }
genesis 362 }
genesis 363 return 0;
genesis 364 }
genesis 365
genesis 366 int64 CWalletTx::GetTxTime() const
genesis 367 {
genesis 368 return nTimeReceived;
genesis 369 }
genesis 370
genesis 371 int CWalletTx::GetRequestCount() const
genesis 372 {
genesis 373
genesis 374 int nRequests = -1;
genesis 375 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 376 {
genesis 377 if (IsCoinBase())
genesis 378 {
genesis 379
genesis 380 if (hashBlock != 0)
genesis 381 {
genesis 382 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
genesis 383 if (mi != pwallet->mapRequestCount.end())
genesis 384 nRequests = (*mi).second;
genesis 385 }
genesis 386 }
genesis 387 else
genesis 388 {
genesis 389
genesis 390 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
genesis 391 if (mi != pwallet->mapRequestCount.end())
genesis 392 {
genesis 393 nRequests = (*mi).second;
genesis 394
genesis 395
genesis 396 if (nRequests == 0 && hashBlock != 0)
genesis 397 {
genesis 398 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
genesis 399 if (mi != pwallet->mapRequestCount.end())
genesis 400 nRequests = (*mi).second;
genesis 401 else
genesis 402 nRequests = 1;
genesis 403 }
genesis 404 }
genesis 405 }
genesis 406 }
genesis 407 return nRequests;
genesis 408 }
genesis 409
genesis 410 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CBitcoinAddress, int64> >& listReceived,
genesis 411 list<pair<CBitcoinAddress, int64> >& listSent, int64& nFee, string& strSentAccount) const
genesis 412 {
genesis 413 nGeneratedImmature = nGeneratedMature = nFee = 0;
genesis 414 listReceived.clear();
genesis 415 listSent.clear();
genesis 416 strSentAccount = strFromAccount;
genesis 417
genesis 418 if (IsCoinBase())
genesis 419 {
genesis 420 if (GetBlocksToMaturity() > 0)
genesis 421 nGeneratedImmature = pwallet->GetCredit(*this);
genesis 422 else
genesis 423 nGeneratedMature = GetCredit();
genesis 424 return;
genesis 425 }
genesis 426
genesis 427
genesis 428 int64 nDebit = GetDebit();
genesis 429 if (nDebit > 0)
genesis 430 {
genesis 431 int64 nValueOut = GetValueOut();
genesis 432 nFee = nDebit - nValueOut;
genesis 433 }
genesis 434
genesis 435
genesis 436
genesis 437 BOOST_FOREACH(const CTxOut& txout, vout)
genesis 438 {
genesis 439 CBitcoinAddress address;
genesis 440 vector<unsigned char> vchPubKey;
genesis 441 if (!ExtractAddress(txout.scriptPubKey, NULL, address))
genesis 442 {
polarbeard_better... 443 printf(SWAR SWAL "unknown transaction type found, tx %s\n",
genesis 444 this->GetHash().ToString().c_str());
genesis 445 address = " unknown ";
genesis 446 }
genesis 447
genesis 448
genesis 449 if (nDebit > 0 && pwallet->IsChange(txout))
genesis 450 continue;
genesis 451
genesis 452 if (nDebit > 0)
genesis 453 listSent.push_back(make_pair(address, txout.nValue));
genesis 454
genesis 455 if (pwallet->IsMine(txout))
genesis 456 listReceived.push_back(make_pair(address, txout.nValue));
genesis 457 }
genesis 458
genesis 459 }
genesis 460
genesis 461 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
genesis 462 int64& nSent, int64& nFee) const
genesis 463 {
genesis 464 nGenerated = nReceived = nSent = nFee = 0;
genesis 465
genesis 466 int64 allGeneratedImmature, allGeneratedMature, allFee;
genesis 467 allGeneratedImmature = allGeneratedMature = allFee = 0;
genesis 468 string strSentAccount;
genesis 469 list<pair<CBitcoinAddress, int64> > listReceived;
genesis 470 list<pair<CBitcoinAddress, int64> > listSent;
genesis 471 GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
genesis 472
genesis 473 if (strAccount == "")
genesis 474 nGenerated = allGeneratedMature;
genesis 475 if (strAccount == strSentAccount)
genesis 476 {
genesis 477 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& s, listSent)
genesis 478 nSent += s.second;
genesis 479 nFee = allFee;
genesis 480 }
genesis 481 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 482 {
genesis 483 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
genesis 484 {
genesis 485 if (pwallet->mapAddressBook.count(r.first))
genesis 486 {
genesis 487 map<CBitcoinAddress, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
genesis 488 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
genesis 489 nReceived += r.second;
genesis 490 }
genesis 491 else if (strAccount.empty())
genesis 492 {
genesis 493 nReceived += r.second;
genesis 494 }
genesis 495 }
genesis 496 }
genesis 497 }
genesis 498
genesis 499 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
genesis 500 {
genesis 501 vtxPrev.clear();
genesis 502
genesis 503 const int COPY_DEPTH = 3;
genesis 504 if (SetMerkleBranch() < COPY_DEPTH)
genesis 505 {
genesis 506 vector<uint256> vWorkQueue;
genesis 507 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 508 vWorkQueue.push_back(txin.prevout.hash);
genesis 509
genesis 510
genesis 511 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 512 {
genesis 513 map<uint256, const CMerkleTx*> mapWalletPrev;
genesis 514 set<uint256> setAlreadyDone;
genesis 515 for (int i = 0; i < vWorkQueue.size(); i++)
genesis 516 {
genesis 517 uint256 hash = vWorkQueue[i];
genesis 518 if (setAlreadyDone.count(hash))
genesis 519 continue;
genesis 520 setAlreadyDone.insert(hash);
genesis 521
genesis 522 CMerkleTx tx;
genesis 523 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
genesis 524 if (mi != pwallet->mapWallet.end())
genesis 525 {
genesis 526 tx = (*mi).second;
genesis 527 BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
genesis 528 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
genesis 529 }
genesis 530 else if (mapWalletPrev.count(hash))
genesis 531 {
genesis 532 tx = *mapWalletPrev[hash];
genesis 533 }
genesis 534 else if (!fClient && txdb.ReadDiskTx(hash, tx))
genesis 535 {
genesis 536 ;
genesis 537 }
genesis 538 else
genesis 539 {
polarbeard_better... 540 printf(SERR SWAL "unsupported tx\n");
genesis 541 continue;
genesis 542 }
genesis 543
genesis 544 int nDepth = tx.SetMerkleBranch();
genesis 545 vtxPrev.push_back(tx);
genesis 546
genesis 547 if (nDepth < COPY_DEPTH)
genesis 548 BOOST_FOREACH(const CTxIn& txin, tx.vin)
genesis 549 vWorkQueue.push_back(txin.prevout.hash);
genesis 550 }
genesis 551 }
genesis 552 }
genesis 553
genesis 554 reverse(vtxPrev.begin(), vtxPrev.end());
genesis 555 }
genesis 556
genesis 557 bool CWalletTx::WriteToDisk()
genesis 558 {
genesis 559 return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
genesis 560 }
genesis 561
genesis 562
genesis 563
genesis 564
genesis 565 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
genesis 566 {
genesis 567 int ret = 0;
genesis 568
genesis 569 CBlockIndex* pindex = pindexStart;
genesis 570 CRITICAL_BLOCK(cs_wallet)
genesis 571 {
genesis 572 while (pindex)
genesis 573 {
genesis 574 CBlock block;
genesis 575 block.ReadFromDisk(pindex, true);
genesis 576 BOOST_FOREACH(CTransaction& tx, block.vtx)
genesis 577 {
genesis 578 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
genesis 579 ret++;
genesis 580 }
genesis 581 pindex = pindex->pnext;
genesis 582 }
genesis 583 }
genesis 584 return ret;
genesis 585 }
genesis 586
genesis 587 void CWallet::ReacceptWalletTransactions()
genesis 588 {
genesis 589 CTxDB txdb("r");
genesis 590 bool fRepeat = true;
genesis 591 while (fRepeat) CRITICAL_BLOCK(cs_wallet)
genesis 592 {
genesis 593 fRepeat = false;
genesis 594 vector<CDiskTxPos> vMissingTx;
genesis 595 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 596 {
genesis 597 CWalletTx& wtx = item.second;
genesis 598 if (wtx.IsCoinBase() && wtx.IsSpent(0))
genesis 599 continue;
genesis 600
genesis 601 CTxIndex txindex;
genesis 602 bool fUpdated = false;
genesis 603 if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
genesis 604 {
genesis 605
genesis 606 if (txindex.vSpent.size() != wtx.vout.size())
genesis 607 {
polarbeard_better... 608 printf(SERR SWAL "tx index spent count differs from output index length\n");
genesis 609 continue;
genesis 610 }
genesis 611 for (int i = 0; i < txindex.vSpent.size(); i++)
genesis 612 {
genesis 613 if (wtx.IsSpent(i))
genesis 614 continue;
genesis 615 if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
genesis 616 {
genesis 617 wtx.MarkSpent(i);
genesis 618 fUpdated = true;
genesis 619 vMissingTx.push_back(txindex.vSpent[i]);
genesis 620 }
genesis 621 }
genesis 622 if (fUpdated)
genesis 623 {
polarbeard_better... 624 printf(SERR SWAL "found spent %s bitcoin on tx %s\n",
polarbeard_better... 625 FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
genesis 626 wtx.MarkDirty();
genesis 627 wtx.WriteToDisk();
genesis 628 }
genesis 629 }
genesis 630 else
genesis 631 {
genesis 632
genesis 633 if (!wtx.IsCoinBase())
genesis 634 wtx.AcceptWalletTransaction(txdb, false);
genesis 635 }
genesis 636 }
genesis 637 if (!vMissingTx.empty())
genesis 638 {
genesis 639
genesis 640 if (ScanForWalletTransactions(pindexGenesisBlock))
genesis 641 fRepeat = true;
genesis 642 }
genesis 643 }
genesis 644 }
genesis 645
genesis 646 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
genesis 647 {
genesis 648 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
genesis 649 {
genesis 650 if (!tx.IsCoinBase())
genesis 651 {
genesis 652 uint256 hash = tx.GetHash();
genesis 653 if (!txdb.ContainsTx(hash))
genesis 654 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
genesis 655 }
genesis 656 }
genesis 657 if (!IsCoinBase())
genesis 658 {
genesis 659 uint256 hash = GetHash();
genesis 660 if (!txdb.ContainsTx(hash))
genesis 661 {
polarbeard_better... 662 printf(SINF SWAL "relaying wallet tx %s\n", hash.ToString().c_str());
genesis 663 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
genesis 664 }
genesis 665 }
genesis 666 }
genesis 667
genesis 668 void CWalletTx::RelayWalletTransaction()
genesis 669 {
genesis 670 CTxDB txdb("r");
genesis 671 RelayWalletTransaction(txdb);
genesis 672 }
genesis 673
genesis 674 void CWallet::ResendWalletTransactions()
genesis 675 {
genesis 676
genesis 677
genesis 678 static int64 nNextTime;
genesis 679 if (GetTime() < nNextTime)
genesis 680 return;
genesis 681 bool fFirst = (nNextTime == 0);
genesis 682 nNextTime = GetTime() + GetRand(30 * 60);
genesis 683 if (fFirst)
genesis 684 return;
genesis 685
genesis 686
genesis 687 static int64 nLastTime;
genesis 688 if (nTimeBestReceived < nLastTime)
genesis 689 return;
genesis 690 nLastTime = GetTime();
genesis 691
genesis 692
polarbeard_better... 693 printf(SWAR SWAL "resending wallet txs\n");
genesis 694 CTxDB txdb("r");
genesis 695 CRITICAL_BLOCK(cs_wallet)
genesis 696 {
genesis 697
genesis 698 multimap<unsigned int, CWalletTx*> mapSorted;
genesis 699 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 700 {
genesis 701 CWalletTx& wtx = item.second;
genesis 702
genesis 703
genesis 704 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
genesis 705 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
genesis 706 }
genesis 707 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
genesis 708 {
genesis 709 CWalletTx& wtx = *item.second;
genesis 710 wtx.RelayWalletTransaction(txdb);
genesis 711 }
genesis 712 }
genesis 713 }
genesis 714
genesis 715
genesis 716
genesis 717
genesis 718
genesis 719
genesis 720
genesis 721
genesis 722
genesis 723
genesis 724
genesis 725
genesis 726 int64 CWallet::GetBalance() const
genesis 727 {
genesis 728 int64 nTotal = 0;
genesis 729 CRITICAL_BLOCK(cs_wallet)
genesis 730 {
genesis 731 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 732 {
genesis 733 const CWalletTx* pcoin = &(*it).second;
genesis 734 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 735 continue;
genesis 736 nTotal += pcoin->GetAvailableCredit();
genesis 737 }
genesis 738 }
genesis 739
genesis 740 return nTotal;
genesis 741 }
genesis 742
genesis 743 int64 CWallet::GetUnconfirmedBalance() const
genesis 744 {
genesis 745 int64 nTotal = 0;
genesis 746 CRITICAL_BLOCK(cs_wallet)
genesis 747 {
genesis 748 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 749 {
genesis 750 const CWalletTx* pcoin = &(*it).second;
genesis 751 if (pcoin->IsFinal() && pcoin->IsConfirmed())
genesis 752 continue;
genesis 753 nTotal += pcoin->GetAvailableCredit();
genesis 754 }
genesis 755 }
genesis 756 return nTotal;
genesis 757 }
genesis 758
genesis 759 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 760 {
genesis 761 setCoinsRet.clear();
genesis 762 nValueRet = 0;
genesis 763
genesis 764
genesis 765 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
genesis 766 coinLowestLarger.first = INT64_MAX;
genesis 767 coinLowestLarger.second.first = NULL;
genesis 768 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
genesis 769 int64 nTotalLower = 0;
genesis 770
genesis 771 CRITICAL_BLOCK(cs_wallet)
genesis 772 {
genesis 773 vector<const CWalletTx*> vCoins;
genesis 774 vCoins.reserve(mapWallet.size());
genesis 775 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 776 vCoins.push_back(&(*it).second);
genesis 777 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
genesis 778
genesis 779 BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
genesis 780 {
genesis 781 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 782 continue;
genesis 783
genesis 784 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
genesis 785 continue;
genesis 786
genesis 787 int nDepth = pcoin->GetDepthInMainChain();
genesis 788 if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
genesis 789 continue;
genesis 790
genesis 791 for (int i = 0; i < pcoin->vout.size(); i++)
genesis 792 {
genesis 793 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
genesis 794 continue;
genesis 795
genesis 796 int64 n = pcoin->vout[i].nValue;
genesis 797
genesis 798 if (n <= 0)
genesis 799 continue;
genesis 800
genesis 801 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
genesis 802
genesis 803 if (n == nTargetValue)
genesis 804 {
genesis 805 setCoinsRet.insert(coin.second);
genesis 806 nValueRet += coin.first;
genesis 807 return true;
genesis 808 }
genesis 809 else if (n < nTargetValue + CENT)
genesis 810 {
genesis 811 vValue.push_back(coin);
genesis 812 nTotalLower += n;
genesis 813 }
genesis 814 else if (n < coinLowestLarger.first)
genesis 815 {
genesis 816 coinLowestLarger = coin;
genesis 817 }
genesis 818 }
genesis 819 }
genesis 820 }
genesis 821
genesis 822 if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
genesis 823 {
genesis 824 for (int i = 0; i < vValue.size(); ++i)
genesis 825 {
genesis 826 setCoinsRet.insert(vValue[i].second);
genesis 827 nValueRet += vValue[i].first;
genesis 828 }
genesis 829 return true;
genesis 830 }
genesis 831
genesis 832 if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
genesis 833 {
genesis 834 if (coinLowestLarger.second.first == NULL)
genesis 835 return false;
genesis 836 setCoinsRet.insert(coinLowestLarger.second);
genesis 837 nValueRet += coinLowestLarger.first;
genesis 838 return true;
genesis 839 }
genesis 840
genesis 841 if (nTotalLower >= nTargetValue + CENT)
genesis 842 nTargetValue += CENT;
genesis 843
genesis 844
genesis 845 sort(vValue.rbegin(), vValue.rend());
genesis 846 vector<char> vfIncluded;
genesis 847 vector<char> vfBest(vValue.size(), true);
genesis 848 int64 nBest = nTotalLower;
genesis 849
genesis 850 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
genesis 851 {
genesis 852 vfIncluded.assign(vValue.size(), false);
genesis 853 int64 nTotal = 0;
genesis 854 bool fReachedTarget = false;
genesis 855 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
genesis 856 {
genesis 857 for (int i = 0; i < vValue.size(); i++)
genesis 858 {
genesis 859 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
genesis 860 {
genesis 861 nTotal += vValue[i].first;
genesis 862 vfIncluded[i] = true;
genesis 863 if (nTotal >= nTargetValue)
genesis 864 {
genesis 865 fReachedTarget = true;
genesis 866 if (nTotal < nBest)
genesis 867 {
genesis 868 nBest = nTotal;
genesis 869 vfBest = vfIncluded;
genesis 870 }
genesis 871 nTotal -= vValue[i].first;
genesis 872 vfIncluded[i] = false;
genesis 873 }
genesis 874 }
genesis 875 }
genesis 876 }
genesis 877 }
genesis 878
genesis 879
genesis 880 if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
genesis 881 {
genesis 882 setCoinsRet.insert(coinLowestLarger.second);
genesis 883 nValueRet += coinLowestLarger.first;
genesis 884 }
genesis 885 else {
genesis 886 for (int i = 0; i < vValue.size(); i++)
genesis 887 if (vfBest[i])
genesis 888 {
genesis 889 setCoinsRet.insert(vValue[i].second);
genesis 890 nValueRet += vValue[i].first;
genesis 891 }
genesis 892
genesis 893
polarbeard_better... 894 std::string str;
genesis 895 for (int i = 0; i < vValue.size(); i++)
genesis 896 if (vfBest[i])
polarbeard_better... 897 str += FormatMoney(vValue[i].first) + (i == vValue.size() - 1 ? "" : " ");
polarbeard_better... 898 printf(SINF SWAL "selecting best output subset: %s\n", str.c_str());
genesis 899 }
genesis 900
genesis 901 return true;
genesis 902 }
genesis 903
genesis 904 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 905 {
genesis 906 return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
genesis 907 SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
genesis 908 SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
genesis 909 }
genesis 910
genesis 911
genesis 912
genesis 913
genesis 914 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 915 {
genesis 916 int64 nValue = 0;
genesis 917 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 918 {
genesis 919 if (nValue < 0)
genesis 920 return false;
genesis 921 nValue += s.second;
genesis 922 }
genesis 923 if (vecSend.empty() || nValue < 0)
genesis 924 return false;
genesis 925
genesis 926 wtxNew.pwallet = this;
genesis 927
genesis 928 CRITICAL_BLOCK(cs_main)
genesis 929 CRITICAL_BLOCK(cs_wallet)
genesis 930 {
genesis 931
genesis 932 CTxDB txdb("r");
genesis 933 {
genesis 934 nFeeRet = nTransactionFee;
genesis 935 loop
genesis 936 {
genesis 937 wtxNew.vin.clear();
genesis 938 wtxNew.vout.clear();
genesis 939 wtxNew.fFromMe = true;
genesis 940
genesis 941 int64 nTotalValue = nValue + nFeeRet;
genesis 942 double dPriority = 0;
genesis 943
genesis 944 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 945 wtxNew.vout.push_back(CTxOut(s.second, s.first));
genesis 946
genesis 947
genesis 948 set<pair<const CWalletTx*,unsigned int> > setCoins;
genesis 949 int64 nValueIn = 0;
genesis 950 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
genesis 951 return false;
genesis 952 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
genesis 953 {
genesis 954 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
genesis 955 dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
genesis 956 }
genesis 957
genesis 958 int64 nChange = nValueIn - nValue - nFeeRet;
genesis 959
genesis 960
genesis 961 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
genesis 962 {
genesis 963 int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
genesis 964 nChange -= nMoveToFee;
genesis 965 nFeeRet += nMoveToFee;
genesis 966 }
genesis 967
genesis 968 if (nChange > 0)
genesis 969 {
genesis 970
genesis 971
genesis 972
genesis 973
genesis 974
genesis 975
genesis 976
genesis 977
genesis 978 vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
genesis 979
genesis 980
genesis 981
genesis 982 CScript scriptChange;
genesis 983 if (vecSend[0].first.GetBitcoinAddress().IsValid())
genesis 984 scriptChange.SetBitcoinAddress(vchPubKey);
genesis 985 else
genesis 986 scriptChange << vchPubKey << OP_CHECKSIG;
genesis 987
genesis 988
genesis 989 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
genesis 990 wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
genesis 991 }
genesis 992 else
genesis 993 reservekey.ReturnKey();
genesis 994
genesis 995
genesis 996 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 997 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
genesis 998
genesis 999
genesis 1000 int nIn = 0;
genesis 1001 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 1002 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
genesis 1003 return false;
genesis 1004
genesis 1005
genesis 1006 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
genesis 1007 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
genesis 1008 return false;
genesis 1009 dPriority /= nBytes;
genesis 1010
genesis 1011
genesis 1012 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
genesis 1013 bool fAllowFree = CTransaction::AllowFree(dPriority);
genesis 1014 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
genesis 1015 if (nFeeRet < max(nPayFee, nMinFee))
genesis 1016 {
genesis 1017 nFeeRet = max(nPayFee, nMinFee);
genesis 1018 continue;
genesis 1019 }
genesis 1020
genesis 1021
genesis 1022 wtxNew.AddSupportingTransactions(txdb);
genesis 1023 wtxNew.fTimeReceivedIsTxTime = true;
genesis 1024
genesis 1025 break;
genesis 1026 }
genesis 1027 }
genesis 1028 }
genesis 1029 return true;
genesis 1030 }
genesis 1031
genesis 1032 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 1033 {
genesis 1034 vector< pair<CScript, int64> > vecSend;
genesis 1035 vecSend.push_back(make_pair(scriptPubKey, nValue));
genesis 1036 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
genesis 1037 }
genesis 1038
genesis 1039
genesis 1040 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
genesis 1041 {
genesis 1042 CRITICAL_BLOCK(cs_main)
genesis 1043 CRITICAL_BLOCK(cs_wallet)
genesis 1044 {
polarbeard_better... 1045 printf(SINF SWAL "commit tx %s\n", wtxNew.ToString().c_str());
genesis 1046 {
genesis 1047
genesis 1048
genesis 1049
genesis 1050 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
genesis 1051
genesis 1052
genesis 1053 reservekey.KeepKey();
genesis 1054
genesis 1055
genesis 1056
genesis 1057 AddToWallet(wtxNew);
genesis 1058
genesis 1059
genesis 1060 set<CWalletTx*> setCoins;
genesis 1061 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
genesis 1062 {
genesis 1063 CWalletTx &coin = mapWallet[txin.prevout.hash];
genesis 1064 coin.pwallet = this;
genesis 1065 coin.MarkSpent(txin.prevout.n);
genesis 1066 coin.WriteToDisk();
genesis 1067 vWalletUpdated.push_back(coin.GetHash());
genesis 1068 }
genesis 1069
genesis 1070 if (fFileBacked)
genesis 1071 delete pwalletdb;
genesis 1072 }
genesis 1073
genesis 1074
genesis 1075 mapRequestCount[wtxNew.GetHash()] = 0;
genesis 1076
genesis 1077
genesis 1078 if (!wtxNew.AcceptToMemoryPool())
genesis 1079 {
genesis 1080
polarbeard_better... 1081 printf(SERR SWAL "tx found non-valid while commiting");
genesis 1082 return false;
genesis 1083 }
genesis 1084 wtxNew.RelayWalletTransaction();
genesis 1085 }
genesis 1086 MainFrameRepaint();
genesis 1087 return true;
genesis 1088 }
genesis 1089
genesis 1090
genesis 1091
genesis 1092
genesis 1093 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1094 {
genesis 1095 CReserveKey reservekey(this);
genesis 1096 int64 nFeeRequired;
genesis 1097
genesis 1098 if (IsLocked())
genesis 1099 {
genesis 1100 string strError = _("Error: Wallet locked, unable to create transaction ");
polarbeard_better... 1101 printf(SERR SWAL "send money failed with error %s\n", strError.c_str());
genesis 1102 return strError;
genesis 1103 }
genesis 1104 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
genesis 1105 {
genesis 1106 string strError;
genesis 1107 if (nValue + nFeeRequired > GetBalance())
polarbeard_better... 1108 strError += strprintf("tx requires a tx fee of at"
polarbeard_better... 1109 " least %s because of its amount, complexity, or use of recently"
polarbeard_better... 1110 " received funds", FormatMoney(nFeeRequired).c_str());
genesis 1111 else
polarbeard_better... 1112 strError += strprintf("tx creation failed");
polarbeard_better... 1113 printf(SERR SWAL "send money failed with error: %s", strError.c_str());
genesis 1114 return strError;
genesis 1115 }
genesis 1116
genesis 1117 if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
genesis 1118 return "ABORTED";
genesis 1119
genesis 1120 if (!CommitTransaction(wtxNew, reservekey))
genesis 1121 return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
genesis 1122
genesis 1123 MainFrameRepaint();
genesis 1124 return "";
genesis 1125 }
genesis 1126
genesis 1127
genesis 1128
genesis 1129 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1130 {
genesis 1131
genesis 1132 if (nValue <= 0)
genesis 1133 return _("Invalid amount");
genesis 1134 if (nValue + nTransactionFee > GetBalance())
genesis 1135 return _("Insufficient funds");
genesis 1136
genesis 1137
genesis 1138 CScript scriptPubKey;
genesis 1139 scriptPubKey.SetBitcoinAddress(address);
genesis 1140
genesis 1141 return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
genesis 1142 }
genesis 1143
genesis 1144
genesis 1145
genesis 1146
genesis 1147 int CWallet::LoadWallet(bool& fFirstRunRet)
genesis 1148 {
genesis 1149 if (!fFileBacked)
genesis 1150 return false;
genesis 1151 fFirstRunRet = false;
genesis 1152 int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
genesis 1153 if (nLoadWalletRet == DB_NEED_REWRITE)
genesis 1154 {
genesis 1155 if (CDB::Rewrite(strWalletFile, "\x04pool"))
genesis 1156 {
genesis 1157 setKeyPool.clear();
genesis 1158
genesis 1159
genesis 1160
genesis 1161 }
genesis 1162 nLoadWalletRet = DB_NEED_REWRITE;
genesis 1163 }
genesis 1164
genesis 1165 if (nLoadWalletRet != DB_LOAD_OK)
genesis 1166 return nLoadWalletRet;
genesis 1167 fFirstRunRet = vchDefaultKey.empty();
genesis 1168
genesis 1169 if (!HaveKey(Hash160(vchDefaultKey)))
genesis 1170 {
genesis 1171
genesis 1172 RandAddSeedPerfmon();
genesis 1173
genesis 1174 std::vector<unsigned char> newDefaultKey;
genesis 1175 if (!GetKeyFromPool(newDefaultKey, false))
genesis 1176 return DB_LOAD_FAIL;
genesis 1177 SetDefaultKey(newDefaultKey);
genesis 1178 if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
genesis 1179 return DB_LOAD_FAIL;
genesis 1180 }
genesis 1181
genesis 1182 CreateThread(ThreadFlushWalletDB, &strWalletFile);
genesis 1183 return DB_LOAD_OK;
genesis 1184 }
genesis 1185
genesis 1186
genesis 1187 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
genesis 1188 {
genesis 1189 mapAddressBook[address] = strName;
genesis 1190 if (!fFileBacked)
genesis 1191 return false;
genesis 1192 return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
genesis 1193 }
genesis 1194
genesis 1195 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
genesis 1196 {
genesis 1197 mapAddressBook.erase(address);
genesis 1198 if (!fFileBacked)
genesis 1199 return false;
genesis 1200 return CWalletDB(strWalletFile).EraseName(address.ToString());
genesis 1201 }
genesis 1202
genesis 1203
genesis 1204 void CWallet::PrintWallet(const CBlock& block)
genesis 1205 {
genesis 1206 CRITICAL_BLOCK(cs_wallet)
genesis 1207 {
genesis 1208 if (mapWallet.count(block.vtx[0].GetHash()))
genesis 1209 {
genesis 1210 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
polarbeard_better... 1211 printf(SINF SWAL "depth is %d, blocks to maturity is %d and credit is %d\n",
polarbeard_better... 1212 wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
genesis 1213 }
genesis 1214 }
genesis 1215 }
genesis 1216
genesis 1217 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
genesis 1218 {
genesis 1219 CRITICAL_BLOCK(cs_wallet)
genesis 1220 {
genesis 1221 map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
genesis 1222 if (mi != mapWallet.end())
genesis 1223 {
genesis 1224 wtx = (*mi).second;
genesis 1225 return true;
genesis 1226 }
genesis 1227 }
genesis 1228 return false;
genesis 1229 }
genesis 1230
genesis 1231 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
genesis 1232 {
genesis 1233 if (fFileBacked)
genesis 1234 {
genesis 1235 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
genesis 1236 return false;
genesis 1237 }
genesis 1238 vchDefaultKey = vchPubKey;
genesis 1239 return true;
genesis 1240 }
genesis 1241
genesis 1242 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
genesis 1243 {
genesis 1244 if (!pwallet->fFileBacked)
genesis 1245 return false;
genesis 1246 strWalletFileOut = pwallet->strWalletFile;
genesis 1247 return true;
genesis 1248 }
genesis 1249
genesis 1250
genesis 1251
genesis 1252
genesis 1253
genesis 1254 bool CWallet::NewKeyPool()
genesis 1255 {
genesis 1256 CRITICAL_BLOCK(cs_wallet)
genesis 1257 {
genesis 1258 CWalletDB walletdb(strWalletFile);
genesis 1259 BOOST_FOREACH(int64 nIndex, setKeyPool)
genesis 1260 walletdb.ErasePool(nIndex);
genesis 1261 setKeyPool.clear();
genesis 1262
genesis 1263 if (IsLocked())
genesis 1264 return false;
genesis 1265
genesis 1266 int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
genesis 1267 for (int i = 0; i < nKeys; i++)
genesis 1268 {
genesis 1269 int64 nIndex = i+1;
genesis 1270 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
genesis 1271 setKeyPool.insert(nIndex);
genesis 1272 }
polarbeard_better... 1273 printf(SINF SWAL "%"PRI64d" new keys written\n", nKeys);
genesis 1274 }
genesis 1275 return true;
genesis 1276 }
genesis 1277
genesis 1278 bool CWallet::TopUpKeyPool()
genesis 1279 {
genesis 1280 CRITICAL_BLOCK(cs_wallet)
genesis 1281 {
genesis 1282 if (IsLocked())
genesis 1283 return false;
genesis 1284
genesis 1285 CWalletDB walletdb(strWalletFile);
genesis 1286
genesis 1287
genesis 1288 int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
genesis 1289 while (setKeyPool.size() < nTargetSize+1)
genesis 1290 {
genesis 1291 int64 nEnd = 1;
genesis 1292 if (!setKeyPool.empty())
genesis 1293 nEnd = *(--setKeyPool.end()) + 1;
genesis 1294 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
genesis 1295 throw runtime_error("TopUpKeyPool() : writing generated key failed");
genesis 1296 setKeyPool.insert(nEnd);
polarbeard_better... 1297 printf(SINF SWAL "added key %"PRI64d", current size is %d\n", nEnd, setKeyPool.size());
genesis 1298 }
genesis 1299 }
genesis 1300 return true;
genesis 1301 }
genesis 1302
genesis 1303 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
genesis 1304 {
genesis 1305 nIndex = -1;
genesis 1306 keypool.vchPubKey.clear();
genesis 1307 CRITICAL_BLOCK(cs_wallet)
genesis 1308 {
genesis 1309 if (!IsLocked())
genesis 1310 TopUpKeyPool();
genesis 1311
genesis 1312
genesis 1313 if(setKeyPool.empty())
genesis 1314 return;
genesis 1315
genesis 1316 CWalletDB walletdb(strWalletFile);
genesis 1317
genesis 1318 nIndex = *(setKeyPool.begin());
genesis 1319 setKeyPool.erase(setKeyPool.begin());
genesis 1320 if (!walletdb.ReadPool(nIndex, keypool))
genesis 1321 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
genesis 1322 if (!HaveKey(Hash160(keypool.vchPubKey)))
genesis 1323 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
genesis 1324 assert(!keypool.vchPubKey.empty());
polarbeard_better... 1325 printf(SINF SWAL "keypool reserve %"PRI64d"\n", nIndex);
genesis 1326 }
genesis 1327 }
genesis 1328
genesis 1329 void CWallet::KeepKey(int64 nIndex)
genesis 1330 {
genesis 1331
genesis 1332 if (fFileBacked)
genesis 1333 {
genesis 1334 CWalletDB walletdb(strWalletFile);
genesis 1335 walletdb.ErasePool(nIndex);
genesis 1336 }
polarbeard_better... 1337 printf(SINF SWAL "keypool keep %"PRI64d"\n", nIndex);
genesis 1338 }
genesis 1339
genesis 1340 void CWallet::ReturnKey(int64 nIndex)
genesis 1341 {
genesis 1342
genesis 1343 CRITICAL_BLOCK(cs_wallet)
genesis 1344 setKeyPool.insert(nIndex);
polarbeard_better... 1345 printf(SINF SWAL "keypool return %"PRI64d"\n", nIndex);
genesis 1346 }
genesis 1347
genesis 1348 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
genesis 1349 {
genesis 1350 int64 nIndex = 0;
genesis 1351 CKeyPool keypool;
genesis 1352 CRITICAL_BLOCK(cs_wallet)
genesis 1353 {
genesis 1354 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1355 if (nIndex == -1)
genesis 1356 {
genesis 1357 if (fAllowReuse && !vchDefaultKey.empty())
genesis 1358 {
genesis 1359 result = vchDefaultKey;
genesis 1360 return true;
genesis 1361 }
genesis 1362 if (IsLocked()) return false;
genesis 1363 result = GenerateNewKey();
genesis 1364 return true;
genesis 1365 }
genesis 1366 KeepKey(nIndex);
genesis 1367 result = keypool.vchPubKey;
genesis 1368 }
genesis 1369 return true;
genesis 1370 }
genesis 1371
genesis 1372 int64 CWallet::GetOldestKeyPoolTime()
genesis 1373 {
genesis 1374 int64 nIndex = 0;
genesis 1375 CKeyPool keypool;
genesis 1376 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1377 if (nIndex == -1)
genesis 1378 return GetTime();
genesis 1379 ReturnKey(nIndex);
genesis 1380 return keypool.nTime;
genesis 1381 }
genesis 1382
genesis 1383 vector<unsigned char> CReserveKey::GetReservedKey()
genesis 1384 {
genesis 1385 if (nIndex == -1)
genesis 1386 {
genesis 1387 CKeyPool keypool;
genesis 1388 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1389 if (nIndex != -1)
genesis 1390 vchPubKey = keypool.vchPubKey;
genesis 1391 else
genesis 1392 {
polarbeard_better... 1393 printf(SWAR SWAL "using default key instead of a new key, top up your keypool\n");
genesis 1394 vchPubKey = pwallet->vchDefaultKey;
genesis 1395 }
genesis 1396 }
genesis 1397 assert(!vchPubKey.empty());
genesis 1398 return vchPubKey;
genesis 1399 }
genesis 1400
genesis 1401 void CReserveKey::KeepKey()
genesis 1402 {
genesis 1403 if (nIndex != -1)
genesis 1404 pwallet->KeepKey(nIndex);
genesis 1405 nIndex = -1;
genesis 1406 vchPubKey.clear();
genesis 1407 }
genesis 1408
genesis 1409 void CReserveKey::ReturnKey()
genesis 1410 {
genesis 1411 if (nIndex != -1)
genesis 1412 pwallet->ReturnKey(nIndex);
genesis 1413 nIndex = -1;
genesis 1414 vchPubKey.clear();
genesis 1415 }
genesis 1416