raw
genesis                 1 // Copyright (c) 2009-2010 Satoshi Nakamoto
genesis 2 // Copyright (c) 2011 The Bitcoin developers
genesis 3 // Distributed under the MIT/X11 software license, see the accompanying
genesis 4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
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 // mapWallet
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
genesis 95 printf("Wallet passphrase changed to an nDeriveIterations of %i\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 // This class implements an addrIncoming entry that causes pre-0.4
genesis 114 // clients to crash on startup if reading a private-key-encrypted wallet.
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
genesis 154 printf("Encrypting Wallet with an nDeriveIterations of %i\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); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
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); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
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 // Need to completely rewrite the wallet file; if we don't, bdb might keep
genesis 195 // bits of the unencrypted private key in slack space in the database file.
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 // Anytime a signature is successfully verified, it's proof the outpoint is spent.
genesis 205 // Update the wallet spent flag if it doesn't know due to wallet.dat being
genesis 206 // restored from backup or the user making copies of wallet.dat.
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 {
genesis 217 printf("WalletUpdateSpent found spent coin %sbc %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 // Inserts only if not already there, returns tx inserted or tx found
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 // Merge
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 //// debug print
genesis 264 printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
genesis 265
genesis 266 // Write to disk
genesis 267 if (fInsertedNew || fUpdated)
genesis 268 if (!wtx.WriteToDisk())
genesis 269 return false;
genesis 270 #ifndef QT_GUI
genesis 271 // If default receiving address gets used, replace it with a new one
genesis 272 CScript scriptDefaultKey;
genesis 273 scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
genesis 274 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis 275 {
genesis 276 if (txout.scriptPubKey == scriptDefaultKey)
genesis 277 {
genesis 278 std::vector<unsigned char> newDefaultKey;
genesis 279 if (GetKeyFromPool(newDefaultKey, false))
genesis 280 {
genesis 281 SetDefaultKey(newDefaultKey);
genesis 282 SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
genesis 283 }
genesis 284 }
genesis 285 }
genesis 286 #endif
genesis 287 // Notify UI
genesis 288 vWalletUpdated.push_back(hash);
genesis 289
genesis 290 // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
genesis 291 WalletUpdateSpent(wtx);
genesis 292 }
genesis 293
genesis 294 // Refresh UI
genesis 295 MainFrameRepaint();
genesis 296 return true;
genesis 297 }
genesis 298
genesis 299 // Add a transaction to the wallet, or update it.
genesis 300 // pblock is optional, but should be provided if the transaction is known to be in a block.
genesis 301 // If fUpdate is true, existing transactions will be updated.
genesis 302 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
genesis 303 {
genesis 304 uint256 hash = tx.GetHash();
genesis 305 CRITICAL_BLOCK(cs_wallet)
genesis 306 {
genesis 307 bool fExisted = mapWallet.count(hash);
genesis 308 if (fExisted && !fUpdate) return false;
genesis 309 if (fExisted || IsMine(tx) || IsFromMe(tx))
genesis 310 {
genesis 311 CWalletTx wtx(this,tx);
genesis 312 // Get merkle branch if transaction was found in a block
genesis 313 if (pblock)
genesis 314 wtx.SetMerkleBranch(pblock);
genesis 315 return AddToWallet(wtx);
genesis 316 }
genesis 317 else
genesis 318 WalletUpdateSpent(tx);
genesis 319 }
genesis 320 return false;
genesis 321 }
genesis 322
genesis 323 bool CWallet::EraseFromWallet(uint256 hash)
genesis 324 {
genesis 325 if (!fFileBacked)
genesis 326 return false;
genesis 327 CRITICAL_BLOCK(cs_wallet)
genesis 328 {
genesis 329 if (mapWallet.erase(hash))
genesis 330 CWalletDB(strWalletFile).EraseTx(hash);
genesis 331 }
genesis 332 return true;
genesis 333 }
genesis 334
genesis 335
genesis 336 bool CWallet::IsMine(const CTxIn &txin) const
genesis 337 {
genesis 338 CRITICAL_BLOCK(cs_wallet)
genesis 339 {
genesis 340 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
genesis 341 if (mi != mapWallet.end())
genesis 342 {
genesis 343 const CWalletTx& prev = (*mi).second;
genesis 344 if (txin.prevout.n < prev.vout.size())
genesis 345 if (IsMine(prev.vout[txin.prevout.n]))
genesis 346 return true;
genesis 347 }
genesis 348 }
genesis 349 return false;
genesis 350 }
genesis 351
genesis 352 int64 CWallet::GetDebit(const CTxIn &txin) const
genesis 353 {
genesis 354 CRITICAL_BLOCK(cs_wallet)
genesis 355 {
genesis 356 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
genesis 357 if (mi != mapWallet.end())
genesis 358 {
genesis 359 const CWalletTx& prev = (*mi).second;
genesis 360 if (txin.prevout.n < prev.vout.size())
genesis 361 if (IsMine(prev.vout[txin.prevout.n]))
genesis 362 return prev.vout[txin.prevout.n].nValue;
genesis 363 }
genesis 364 }
genesis 365 return 0;
genesis 366 }
genesis 367
genesis 368 int64 CWalletTx::GetTxTime() const
genesis 369 {
genesis 370 return nTimeReceived;
genesis 371 }
genesis 372
genesis 373 int CWalletTx::GetRequestCount() const
genesis 374 {
genesis 375 // Returns -1 if it wasn't being tracked
genesis 376 int nRequests = -1;
genesis 377 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 378 {
genesis 379 if (IsCoinBase())
genesis 380 {
genesis 381 // Generated block
genesis 382 if (hashBlock != 0)
genesis 383 {
genesis 384 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
genesis 385 if (mi != pwallet->mapRequestCount.end())
genesis 386 nRequests = (*mi).second;
genesis 387 }
genesis 388 }
genesis 389 else
genesis 390 {
genesis 391 // Did anyone request this transaction?
genesis 392 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
genesis 393 if (mi != pwallet->mapRequestCount.end())
genesis 394 {
genesis 395 nRequests = (*mi).second;
genesis 396
genesis 397 // How about the block it's in?
genesis 398 if (nRequests == 0 && hashBlock != 0)
genesis 399 {
genesis 400 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
genesis 401 if (mi != pwallet->mapRequestCount.end())
genesis 402 nRequests = (*mi).second;
genesis 403 else
genesis 404 nRequests = 1; // If it's in someone else's block it must have got out
genesis 405 }
genesis 406 }
genesis 407 }
genesis 408 }
genesis 409 return nRequests;
genesis 410 }
genesis 411
genesis 412 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CBitcoinAddress, int64> >& listReceived,
genesis 413 list<pair<CBitcoinAddress, int64> >& listSent, int64& nFee, string& strSentAccount) const
genesis 414 {
genesis 415 nGeneratedImmature = nGeneratedMature = nFee = 0;
genesis 416 listReceived.clear();
genesis 417 listSent.clear();
genesis 418 strSentAccount = strFromAccount;
genesis 419
genesis 420 if (IsCoinBase())
genesis 421 {
genesis 422 if (GetBlocksToMaturity() > 0)
genesis 423 nGeneratedImmature = pwallet->GetCredit(*this);
genesis 424 else
genesis 425 nGeneratedMature = GetCredit();
genesis 426 return;
genesis 427 }
genesis 428
genesis 429 // Compute fee:
genesis 430 int64 nDebit = GetDebit();
genesis 431 if (nDebit > 0) // debit>0 means we signed/sent this transaction
genesis 432 {
genesis 433 int64 nValueOut = GetValueOut();
genesis 434 nFee = nDebit - nValueOut;
genesis 435 }
genesis 436
genesis 437 // Sent/received. Standard client will never generate a send-to-multiple-recipients,
genesis 438 // but non-standard clients might (so return a list of address/amount pairs)
genesis 439 BOOST_FOREACH(const CTxOut& txout, vout)
genesis 440 {
genesis 441 CBitcoinAddress address;
genesis 442 vector<unsigned char> vchPubKey;
genesis 443 if (!ExtractAddress(txout.scriptPubKey, NULL, address))
genesis 444 {
genesis 445 printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
genesis 446 this->GetHash().ToString().c_str());
genesis 447 address = " unknown ";
genesis 448 }
genesis 449
genesis 450 // Don't report 'change' txouts
genesis 451 if (nDebit > 0 && pwallet->IsChange(txout))
genesis 452 continue;
genesis 453
genesis 454 if (nDebit > 0)
genesis 455 listSent.push_back(make_pair(address, txout.nValue));
genesis 456
genesis 457 if (pwallet->IsMine(txout))
genesis 458 listReceived.push_back(make_pair(address, txout.nValue));
genesis 459 }
genesis 460
genesis 461 }
genesis 462
genesis 463 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
genesis 464 int64& nSent, int64& nFee) const
genesis 465 {
genesis 466 nGenerated = nReceived = nSent = nFee = 0;
genesis 467
genesis 468 int64 allGeneratedImmature, allGeneratedMature, allFee;
genesis 469 allGeneratedImmature = allGeneratedMature = allFee = 0;
genesis 470 string strSentAccount;
genesis 471 list<pair<CBitcoinAddress, int64> > listReceived;
genesis 472 list<pair<CBitcoinAddress, int64> > listSent;
genesis 473 GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
genesis 474
genesis 475 if (strAccount == "")
genesis 476 nGenerated = allGeneratedMature;
genesis 477 if (strAccount == strSentAccount)
genesis 478 {
genesis 479 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& s, listSent)
genesis 480 nSent += s.second;
genesis 481 nFee = allFee;
genesis 482 }
genesis 483 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 484 {
genesis 485 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
genesis 486 {
genesis 487 if (pwallet->mapAddressBook.count(r.first))
genesis 488 {
genesis 489 map<CBitcoinAddress, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
genesis 490 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
genesis 491 nReceived += r.second;
genesis 492 }
genesis 493 else if (strAccount.empty())
genesis 494 {
genesis 495 nReceived += r.second;
genesis 496 }
genesis 497 }
genesis 498 }
genesis 499 }
genesis 500
genesis 501 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
genesis 502 {
genesis 503 vtxPrev.clear();
genesis 504
genesis 505 const int COPY_DEPTH = 3;
genesis 506 if (SetMerkleBranch() < COPY_DEPTH)
genesis 507 {
genesis 508 vector<uint256> vWorkQueue;
genesis 509 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 510 vWorkQueue.push_back(txin.prevout.hash);
genesis 511
genesis 512 // This critsect is OK because txdb is already open
genesis 513 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 514 {
genesis 515 map<uint256, const CMerkleTx*> mapWalletPrev;
genesis 516 set<uint256> setAlreadyDone;
genesis 517 for (int i = 0; i < vWorkQueue.size(); i++)
genesis 518 {
genesis 519 uint256 hash = vWorkQueue[i];
genesis 520 if (setAlreadyDone.count(hash))
genesis 521 continue;
genesis 522 setAlreadyDone.insert(hash);
genesis 523
genesis 524 CMerkleTx tx;
genesis 525 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
genesis 526 if (mi != pwallet->mapWallet.end())
genesis 527 {
genesis 528 tx = (*mi).second;
genesis 529 BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
genesis 530 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
genesis 531 }
genesis 532 else if (mapWalletPrev.count(hash))
genesis 533 {
genesis 534 tx = *mapWalletPrev[hash];
genesis 535 }
genesis 536 else if (!fClient && txdb.ReadDiskTx(hash, tx))
genesis 537 {
genesis 538 ;
genesis 539 }
genesis 540 else
genesis 541 {
genesis 542 printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
genesis 543 continue;
genesis 544 }
genesis 545
genesis 546 int nDepth = tx.SetMerkleBranch();
genesis 547 vtxPrev.push_back(tx);
genesis 548
genesis 549 if (nDepth < COPY_DEPTH)
genesis 550 BOOST_FOREACH(const CTxIn& txin, tx.vin)
genesis 551 vWorkQueue.push_back(txin.prevout.hash);
genesis 552 }
genesis 553 }
genesis 554 }
genesis 555
genesis 556 reverse(vtxPrev.begin(), vtxPrev.end());
genesis 557 }
genesis 558
genesis 559 bool CWalletTx::WriteToDisk()
genesis 560 {
genesis 561 return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
genesis 562 }
genesis 563
genesis 564 // Scan the block chain (starting in pindexStart) for transactions
genesis 565 // from or to us. If fUpdate is true, found transactions that already
genesis 566 // exist in the wallet will be updated.
genesis 567 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
genesis 568 {
genesis 569 int ret = 0;
genesis 570
genesis 571 CBlockIndex* pindex = pindexStart;
genesis 572 CRITICAL_BLOCK(cs_wallet)
genesis 573 {
genesis 574 while (pindex)
genesis 575 {
genesis 576 CBlock block;
genesis 577 block.ReadFromDisk(pindex, true);
genesis 578 BOOST_FOREACH(CTransaction& tx, block.vtx)
genesis 579 {
genesis 580 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
genesis 581 ret++;
genesis 582 }
genesis 583 pindex = pindex->pnext;
genesis 584 }
genesis 585 }
genesis 586 return ret;
genesis 587 }
genesis 588
genesis 589 void CWallet::ReacceptWalletTransactions()
genesis 590 {
genesis 591 CTxDB txdb("r");
genesis 592 bool fRepeat = true;
genesis 593 while (fRepeat) CRITICAL_BLOCK(cs_wallet)
genesis 594 {
genesis 595 fRepeat = false;
genesis 596 vector<CDiskTxPos> vMissingTx;
genesis 597 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 598 {
genesis 599 CWalletTx& wtx = item.second;
genesis 600 if (wtx.IsCoinBase() && wtx.IsSpent(0))
genesis 601 continue;
genesis 602
genesis 603 CTxIndex txindex;
genesis 604 bool fUpdated = false;
genesis 605 if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
genesis 606 {
genesis 607 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
genesis 608 if (txindex.vSpent.size() != wtx.vout.size())
genesis 609 {
genesis 610 printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
genesis 611 continue;
genesis 612 }
genesis 613 for (int i = 0; i < txindex.vSpent.size(); i++)
genesis 614 {
genesis 615 if (wtx.IsSpent(i))
genesis 616 continue;
genesis 617 if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
genesis 618 {
genesis 619 wtx.MarkSpent(i);
genesis 620 fUpdated = true;
genesis 621 vMissingTx.push_back(txindex.vSpent[i]);
genesis 622 }
genesis 623 }
genesis 624 if (fUpdated)
genesis 625 {
genesis 626 printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
genesis 627 wtx.MarkDirty();
genesis 628 wtx.WriteToDisk();
genesis 629 }
genesis 630 }
genesis 631 else
genesis 632 {
genesis 633 // Reaccept any txes of ours that aren't already in a block
genesis 634 if (!wtx.IsCoinBase())
genesis 635 wtx.AcceptWalletTransaction(txdb, false);
genesis 636 }
genesis 637 }
genesis 638 if (!vMissingTx.empty())
genesis 639 {
genesis 640 // TODO: optimize this to scan just part of the block chain?
genesis 641 if (ScanForWalletTransactions(pindexGenesisBlock))
genesis 642 fRepeat = true; // Found missing transactions: re-do Reaccept.
genesis 643 }
genesis 644 }
genesis 645 }
genesis 646
genesis 647 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
genesis 648 {
genesis 649 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
genesis 650 {
genesis 651 if (!tx.IsCoinBase())
genesis 652 {
genesis 653 uint256 hash = tx.GetHash();
genesis 654 if (!txdb.ContainsTx(hash))
genesis 655 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
genesis 656 }
genesis 657 }
genesis 658 if (!IsCoinBase())
genesis 659 {
genesis 660 uint256 hash = GetHash();
genesis 661 if (!txdb.ContainsTx(hash))
genesis 662 {
genesis 663 printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
genesis 664 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
genesis 665 }
genesis 666 }
genesis 667 }
genesis 668
genesis 669 void CWalletTx::RelayWalletTransaction()
genesis 670 {
genesis 671 CTxDB txdb("r");
genesis 672 RelayWalletTransaction(txdb);
genesis 673 }
genesis 674
genesis 675 void CWallet::ResendWalletTransactions()
genesis 676 {
genesis 677 // Do this infrequently and randomly to avoid giving away
genesis 678 // that these are our transactions.
genesis 679 static int64 nNextTime;
genesis 680 if (GetTime() < nNextTime)
genesis 681 return;
genesis 682 bool fFirst = (nNextTime == 0);
genesis 683 nNextTime = GetTime() + GetRand(30 * 60);
genesis 684 if (fFirst)
genesis 685 return;
genesis 686
genesis 687 // Only do it if there's been a new block since last time
genesis 688 static int64 nLastTime;
genesis 689 if (nTimeBestReceived < nLastTime)
genesis 690 return;
genesis 691 nLastTime = GetTime();
genesis 692
genesis 693 // Rebroadcast any of our txes that aren't in a block yet
genesis 694 printf("ResendWalletTransactions()\n");
genesis 695 CTxDB txdb("r");
genesis 696 CRITICAL_BLOCK(cs_wallet)
genesis 697 {
genesis 698 // Sort them in chronological order
genesis 699 multimap<unsigned int, CWalletTx*> mapSorted;
genesis 700 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 701 {
genesis 702 CWalletTx& wtx = item.second;
genesis 703 // Don't rebroadcast until it's had plenty of time that
genesis 704 // it should have gotten in already by now.
genesis 705 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
genesis 706 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
genesis 707 }
genesis 708 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
genesis 709 {
genesis 710 CWalletTx& wtx = *item.second;
genesis 711 wtx.RelayWalletTransaction(txdb);
genesis 712 }
genesis 713 }
genesis 714 }
genesis 715
genesis 716
genesis 717
genesis 718
genesis 719
genesis 720
genesis 721 //////////////////////////////////////////////////////////////////////////////
genesis 722 //
genesis 723 // Actions
genesis 724 //
genesis 725
genesis 726
genesis 727 int64 CWallet::GetBalance() const
genesis 728 {
genesis 729 int64 nTotal = 0;
genesis 730 CRITICAL_BLOCK(cs_wallet)
genesis 731 {
genesis 732 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 733 {
genesis 734 const CWalletTx* pcoin = &(*it).second;
genesis 735 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 736 continue;
genesis 737 nTotal += pcoin->GetAvailableCredit();
genesis 738 }
genesis 739 }
genesis 740
genesis 741 return nTotal;
genesis 742 }
genesis 743
genesis 744 int64 CWallet::GetUnconfirmedBalance() const
genesis 745 {
genesis 746 int64 nTotal = 0;
genesis 747 CRITICAL_BLOCK(cs_wallet)
genesis 748 {
genesis 749 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 750 {
genesis 751 const CWalletTx* pcoin = &(*it).second;
genesis 752 if (pcoin->IsFinal() && pcoin->IsConfirmed())
genesis 753 continue;
genesis 754 nTotal += pcoin->GetAvailableCredit();
genesis 755 }
genesis 756 }
genesis 757 return nTotal;
genesis 758 }
genesis 759
genesis 760 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 761 {
genesis 762 setCoinsRet.clear();
genesis 763 nValueRet = 0;
genesis 764
genesis 765 // List of values less than target
genesis 766 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
genesis 767 coinLowestLarger.first = INT64_MAX;
genesis 768 coinLowestLarger.second.first = NULL;
genesis 769 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
genesis 770 int64 nTotalLower = 0;
genesis 771
genesis 772 CRITICAL_BLOCK(cs_wallet)
genesis 773 {
genesis 774 vector<const CWalletTx*> vCoins;
genesis 775 vCoins.reserve(mapWallet.size());
genesis 776 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 777 vCoins.push_back(&(*it).second);
genesis 778 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
genesis 779
genesis 780 BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
genesis 781 {
genesis 782 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 783 continue;
genesis 784
genesis 785 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
genesis 786 continue;
genesis 787
genesis 788 int nDepth = pcoin->GetDepthInMainChain();
genesis 789 if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
genesis 790 continue;
genesis 791
genesis 792 for (int i = 0; i < pcoin->vout.size(); i++)
genesis 793 {
genesis 794 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
genesis 795 continue;
genesis 796
genesis 797 int64 n = pcoin->vout[i].nValue;
genesis 798
genesis 799 if (n <= 0)
genesis 800 continue;
genesis 801
genesis 802 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
genesis 803
genesis 804 if (n == nTargetValue)
genesis 805 {
genesis 806 setCoinsRet.insert(coin.second);
genesis 807 nValueRet += coin.first;
genesis 808 return true;
genesis 809 }
genesis 810 else if (n < nTargetValue + CENT)
genesis 811 {
genesis 812 vValue.push_back(coin);
genesis 813 nTotalLower += n;
genesis 814 }
genesis 815 else if (n < coinLowestLarger.first)
genesis 816 {
genesis 817 coinLowestLarger = coin;
genesis 818 }
genesis 819 }
genesis 820 }
genesis 821 }
genesis 822
genesis 823 if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
genesis 824 {
genesis 825 for (int i = 0; i < vValue.size(); ++i)
genesis 826 {
genesis 827 setCoinsRet.insert(vValue[i].second);
genesis 828 nValueRet += vValue[i].first;
genesis 829 }
genesis 830 return true;
genesis 831 }
genesis 832
genesis 833 if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
genesis 834 {
genesis 835 if (coinLowestLarger.second.first == NULL)
genesis 836 return false;
genesis 837 setCoinsRet.insert(coinLowestLarger.second);
genesis 838 nValueRet += coinLowestLarger.first;
genesis 839 return true;
genesis 840 }
genesis 841
genesis 842 if (nTotalLower >= nTargetValue + CENT)
genesis 843 nTargetValue += CENT;
genesis 844
genesis 845 // Solve subset sum by stochastic approximation
genesis 846 sort(vValue.rbegin(), vValue.rend());
genesis 847 vector<char> vfIncluded;
genesis 848 vector<char> vfBest(vValue.size(), true);
genesis 849 int64 nBest = nTotalLower;
genesis 850
genesis 851 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
genesis 852 {
genesis 853 vfIncluded.assign(vValue.size(), false);
genesis 854 int64 nTotal = 0;
genesis 855 bool fReachedTarget = false;
genesis 856 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
genesis 857 {
genesis 858 for (int i = 0; i < vValue.size(); i++)
genesis 859 {
genesis 860 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
genesis 861 {
genesis 862 nTotal += vValue[i].first;
genesis 863 vfIncluded[i] = true;
genesis 864 if (nTotal >= nTargetValue)
genesis 865 {
genesis 866 fReachedTarget = true;
genesis 867 if (nTotal < nBest)
genesis 868 {
genesis 869 nBest = nTotal;
genesis 870 vfBest = vfIncluded;
genesis 871 }
genesis 872 nTotal -= vValue[i].first;
genesis 873 vfIncluded[i] = false;
genesis 874 }
genesis 875 }
genesis 876 }
genesis 877 }
genesis 878 }
genesis 879
genesis 880 // If the next larger is still closer, return it
genesis 881 if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
genesis 882 {
genesis 883 setCoinsRet.insert(coinLowestLarger.second);
genesis 884 nValueRet += coinLowestLarger.first;
genesis 885 }
genesis 886 else {
genesis 887 for (int i = 0; i < vValue.size(); i++)
genesis 888 if (vfBest[i])
genesis 889 {
genesis 890 setCoinsRet.insert(vValue[i].second);
genesis 891 nValueRet += vValue[i].first;
genesis 892 }
genesis 893
genesis 894 //// debug print
genesis 895 printf("SelectCoins() best subset: ");
genesis 896 for (int i = 0; i < vValue.size(); i++)
genesis 897 if (vfBest[i])
genesis 898 printf("%s ", FormatMoney(vValue[i].first).c_str());
genesis 899 printf("total %s\n", FormatMoney(nBest).c_str());
genesis 900 }
genesis 901
genesis 902 return true;
genesis 903 }
genesis 904
genesis 905 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 906 {
genesis 907 return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
genesis 908 SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
genesis 909 SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
genesis 910 }
genesis 911
genesis 912
genesis 913
genesis 914
genesis 915 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 916 {
genesis 917 int64 nValue = 0;
genesis 918 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 919 {
genesis 920 if (nValue < 0)
genesis 921 return false;
genesis 922 nValue += s.second;
genesis 923 }
genesis 924 if (vecSend.empty() || nValue < 0)
genesis 925 return false;
genesis 926
genesis 927 wtxNew.pwallet = this;
genesis 928
genesis 929 CRITICAL_BLOCK(cs_main)
genesis 930 CRITICAL_BLOCK(cs_wallet)
genesis 931 {
genesis 932 // txdb must be opened before the mapWallet lock
genesis 933 CTxDB txdb("r");
genesis 934 {
genesis 935 nFeeRet = nTransactionFee;
genesis 936 loop
genesis 937 {
genesis 938 wtxNew.vin.clear();
genesis 939 wtxNew.vout.clear();
genesis 940 wtxNew.fFromMe = true;
genesis 941
genesis 942 int64 nTotalValue = nValue + nFeeRet;
genesis 943 double dPriority = 0;
genesis 944 // vouts to the payees
genesis 945 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 946 wtxNew.vout.push_back(CTxOut(s.second, s.first));
genesis 947
genesis 948 // Choose coins to use
genesis 949 set<pair<const CWalletTx*,unsigned int> > setCoins;
genesis 950 int64 nValueIn = 0;
genesis 951 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
genesis 952 return false;
genesis 953 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
genesis 954 {
genesis 955 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
genesis 956 dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
genesis 957 }
genesis 958
genesis 959 int64 nChange = nValueIn - nValue - nFeeRet;
genesis 960 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
genesis 961 // or until nChange becomes zero
genesis 962 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
genesis 963 {
genesis 964 int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
genesis 965 nChange -= nMoveToFee;
genesis 966 nFeeRet += nMoveToFee;
genesis 967 }
genesis 968
genesis 969 if (nChange > 0)
genesis 970 {
genesis 971 // Note: We use a new key here to keep it from being obvious which side is the change.
genesis 972 // The drawback is that by not reusing a previous key, the change may be lost if a
genesis 973 // backup is restored, if the backup doesn't have the new private key for the change.
genesis 974 // If we reused the old key, it would be possible to add code to look for and
genesis 975 // rediscover unknown transactions that were written with keys of ours to recover
genesis 976 // post-backup change.
genesis 977
genesis 978 // Reserve a new key pair from key pool
genesis 979 vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
genesis 980 // assert(mapKeys.count(vchPubKey));
genesis 981
genesis 982 // Fill a vout to ourself, using same address type as the payment
genesis 983 CScript scriptChange;
genesis 984 if (vecSend[0].first.GetBitcoinAddress().IsValid())
genesis 985 scriptChange.SetBitcoinAddress(vchPubKey);
genesis 986 else
genesis 987 scriptChange << vchPubKey << OP_CHECKSIG;
genesis 988
genesis 989 // Insert change txn at random position:
genesis 990 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
genesis 991 wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
genesis 992 }
genesis 993 else
genesis 994 reservekey.ReturnKey();
genesis 995
genesis 996 // Fill vin
genesis 997 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 998 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
genesis 999
genesis 1000 // Sign
genesis 1001 int nIn = 0;
genesis 1002 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 1003 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
genesis 1004 return false;
genesis 1005
genesis 1006 // Limit size
genesis 1007 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
genesis 1008 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
genesis 1009 return false;
genesis 1010 dPriority /= nBytes;
genesis 1011
genesis 1012 // Check that enough fee is included
genesis 1013 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
genesis 1014 bool fAllowFree = CTransaction::AllowFree(dPriority);
genesis 1015 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
genesis 1016 if (nFeeRet < max(nPayFee, nMinFee))
genesis 1017 {
genesis 1018 nFeeRet = max(nPayFee, nMinFee);
genesis 1019 continue;
genesis 1020 }
genesis 1021
genesis 1022 // Fill vtxPrev by copying from previous transactions vtxPrev
genesis 1023 wtxNew.AddSupportingTransactions(txdb);
genesis 1024 wtxNew.fTimeReceivedIsTxTime = true;
genesis 1025
genesis 1026 break;
genesis 1027 }
genesis 1028 }
genesis 1029 }
genesis 1030 return true;
genesis 1031 }
genesis 1032
genesis 1033 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 1034 {
genesis 1035 vector< pair<CScript, int64> > vecSend;
genesis 1036 vecSend.push_back(make_pair(scriptPubKey, nValue));
genesis 1037 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
genesis 1038 }
genesis 1039
genesis 1040 // Call after CreateTransaction unless you want to abort
genesis 1041 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
genesis 1042 {
genesis 1043 CRITICAL_BLOCK(cs_main)
genesis 1044 CRITICAL_BLOCK(cs_wallet)
genesis 1045 {
genesis 1046 printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
genesis 1047 {
genesis 1048 // This is only to keep the database open to defeat the auto-flush for the
genesis 1049 // duration of this scope. This is the only place where this optimization
genesis 1050 // maybe makes sense; please don't do it anywhere else.
genesis 1051 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
genesis 1052
genesis 1053 // Take key pair from key pool so it won't be used again
genesis 1054 reservekey.KeepKey();
genesis 1055
genesis 1056 // Add tx to wallet, because if it has change it's also ours,
genesis 1057 // otherwise just for transaction history.
genesis 1058 AddToWallet(wtxNew);
genesis 1059
genesis 1060 // Mark old coins as spent
genesis 1061 set<CWalletTx*> setCoins;
genesis 1062 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
genesis 1063 {
genesis 1064 CWalletTx &coin = mapWallet[txin.prevout.hash];
genesis 1065 coin.pwallet = this;
genesis 1066 coin.MarkSpent(txin.prevout.n);
genesis 1067 coin.WriteToDisk();
genesis 1068 vWalletUpdated.push_back(coin.GetHash());
genesis 1069 }
genesis 1070
genesis 1071 if (fFileBacked)
genesis 1072 delete pwalletdb;
genesis 1073 }
genesis 1074
genesis 1075 // Track how many getdata requests our transaction gets
genesis 1076 mapRequestCount[wtxNew.GetHash()] = 0;
genesis 1077
genesis 1078 // Broadcast
genesis 1079 if (!wtxNew.AcceptToMemoryPool())
genesis 1080 {
genesis 1081 // This must not fail. The transaction has already been signed and recorded.
genesis 1082 printf("CommitTransaction() : Error: Transaction not valid");
genesis 1083 return false;
genesis 1084 }
genesis 1085 wtxNew.RelayWalletTransaction();
genesis 1086 }
genesis 1087 MainFrameRepaint();
genesis 1088 return true;
genesis 1089 }
genesis 1090
genesis 1091
genesis 1092
genesis 1093
genesis 1094 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1095 {
genesis 1096 CReserveKey reservekey(this);
genesis 1097 int64 nFeeRequired;
genesis 1098
genesis 1099 if (IsLocked())
genesis 1100 {
genesis 1101 string strError = _("Error: Wallet locked, unable to create transaction ");
genesis 1102 printf("SendMoney() : %s", strError.c_str());
genesis 1103 return strError;
genesis 1104 }
genesis 1105 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
genesis 1106 {
genesis 1107 string strError;
genesis 1108 if (nValue + nFeeRequired > GetBalance())
genesis 1109 strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str());
genesis 1110 else
genesis 1111 strError = _("Error: Transaction creation failed ");
genesis 1112 printf("SendMoney() : %s", strError.c_str());
genesis 1113 return strError;
genesis 1114 }
genesis 1115
genesis 1116 if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
genesis 1117 return "ABORTED";
genesis 1118
genesis 1119 if (!CommitTransaction(wtxNew, reservekey))
genesis 1120 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 1121
genesis 1122 MainFrameRepaint();
genesis 1123 return "";
genesis 1124 }
genesis 1125
genesis 1126
genesis 1127
genesis 1128 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1129 {
genesis 1130 // Check amount
genesis 1131 if (nValue <= 0)
genesis 1132 return _("Invalid amount");
genesis 1133 if (nValue + nTransactionFee > GetBalance())
genesis 1134 return _("Insufficient funds");
genesis 1135
genesis 1136 // Parse bitcoin address
genesis 1137 CScript scriptPubKey;
genesis 1138 scriptPubKey.SetBitcoinAddress(address);
genesis 1139
genesis 1140 return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
genesis 1141 }
genesis 1142
genesis 1143
genesis 1144
genesis 1145
genesis 1146 int CWallet::LoadWallet(bool& fFirstRunRet)
genesis 1147 {
genesis 1148 if (!fFileBacked)
genesis 1149 return false;
genesis 1150 fFirstRunRet = false;
genesis 1151 int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
genesis 1152 if (nLoadWalletRet == DB_NEED_REWRITE)
genesis 1153 {
genesis 1154 if (CDB::Rewrite(strWalletFile, "\x04pool"))
genesis 1155 {
genesis 1156 setKeyPool.clear();
genesis 1157 // Note: can't top-up keypool here, because wallet is locked.
genesis 1158 // User will be prompted to unlock wallet the next operation
genesis 1159 // the requires a new key.
genesis 1160 }
genesis 1161 nLoadWalletRet = DB_NEED_REWRITE;
genesis 1162 }
genesis 1163
genesis 1164 if (nLoadWalletRet != DB_LOAD_OK)
genesis 1165 return nLoadWalletRet;
genesis 1166 fFirstRunRet = vchDefaultKey.empty();
genesis 1167
genesis 1168 if (!HaveKey(Hash160(vchDefaultKey)))
genesis 1169 {
genesis 1170 // Create new keyUser and set as default key
genesis 1171 RandAddSeedPerfmon();
genesis 1172
genesis 1173 std::vector<unsigned char> newDefaultKey;
genesis 1174 if (!GetKeyFromPool(newDefaultKey, false))
genesis 1175 return DB_LOAD_FAIL;
genesis 1176 SetDefaultKey(newDefaultKey);
genesis 1177 if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
genesis 1178 return DB_LOAD_FAIL;
genesis 1179 }
genesis 1180
genesis 1181 CreateThread(ThreadFlushWalletDB, &strWalletFile);
genesis 1182 return DB_LOAD_OK;
genesis 1183 }
genesis 1184
genesis 1185
genesis 1186 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
genesis 1187 {
genesis 1188 mapAddressBook[address] = strName;
genesis 1189 if (!fFileBacked)
genesis 1190 return false;
genesis 1191 return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
genesis 1192 }
genesis 1193
genesis 1194 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
genesis 1195 {
genesis 1196 mapAddressBook.erase(address);
genesis 1197 if (!fFileBacked)
genesis 1198 return false;
genesis 1199 return CWalletDB(strWalletFile).EraseName(address.ToString());
genesis 1200 }
genesis 1201
genesis 1202
genesis 1203 void CWallet::PrintWallet(const CBlock& block)
genesis 1204 {
genesis 1205 CRITICAL_BLOCK(cs_wallet)
genesis 1206 {
genesis 1207 if (mapWallet.count(block.vtx[0].GetHash()))
genesis 1208 {
genesis 1209 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
genesis 1210 printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
genesis 1211 }
genesis 1212 }
genesis 1213 printf("\n");
genesis 1214 }
genesis 1215
genesis 1216 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
genesis 1217 {
genesis 1218 CRITICAL_BLOCK(cs_wallet)
genesis 1219 {
genesis 1220 map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
genesis 1221 if (mi != mapWallet.end())
genesis 1222 {
genesis 1223 wtx = (*mi).second;
genesis 1224 return true;
genesis 1225 }
genesis 1226 }
genesis 1227 return false;
genesis 1228 }
genesis 1229
genesis 1230 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
genesis 1231 {
genesis 1232 if (fFileBacked)
genesis 1233 {
genesis 1234 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
genesis 1235 return false;
genesis 1236 }
genesis 1237 vchDefaultKey = vchPubKey;
genesis 1238 return true;
genesis 1239 }
genesis 1240
genesis 1241 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
genesis 1242 {
genesis 1243 if (!pwallet->fFileBacked)
genesis 1244 return false;
genesis 1245 strWalletFileOut = pwallet->strWalletFile;
genesis 1246 return true;
genesis 1247 }
genesis 1248
genesis 1249 //
genesis 1250 // Mark old keypool keys as used,
genesis 1251 // and generate all new keys
genesis 1252 //
genesis 1253 bool CWallet::NewKeyPool()
genesis 1254 {
genesis 1255 CRITICAL_BLOCK(cs_wallet)
genesis 1256 {
genesis 1257 CWalletDB walletdb(strWalletFile);
genesis 1258 BOOST_FOREACH(int64 nIndex, setKeyPool)
genesis 1259 walletdb.ErasePool(nIndex);
genesis 1260 setKeyPool.clear();
genesis 1261
genesis 1262 if (IsLocked())
genesis 1263 return false;
genesis 1264
genesis 1265 int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
genesis 1266 for (int i = 0; i < nKeys; i++)
genesis 1267 {
genesis 1268 int64 nIndex = i+1;
genesis 1269 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
genesis 1270 setKeyPool.insert(nIndex);
genesis 1271 }
genesis 1272 printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
genesis 1273 }
genesis 1274 return true;
genesis 1275 }
genesis 1276
genesis 1277 bool CWallet::TopUpKeyPool()
genesis 1278 {
genesis 1279 CRITICAL_BLOCK(cs_wallet)
genesis 1280 {
genesis 1281 if (IsLocked())
genesis 1282 return false;
genesis 1283
genesis 1284 CWalletDB walletdb(strWalletFile);
genesis 1285
genesis 1286 // Top up key pool
genesis 1287 int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
genesis 1288 while (setKeyPool.size() < nTargetSize+1)
genesis 1289 {
genesis 1290 int64 nEnd = 1;
genesis 1291 if (!setKeyPool.empty())
genesis 1292 nEnd = *(--setKeyPool.end()) + 1;
genesis 1293 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
genesis 1294 throw runtime_error("TopUpKeyPool() : writing generated key failed");
genesis 1295 setKeyPool.insert(nEnd);
genesis 1296 printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
genesis 1297 }
genesis 1298 }
genesis 1299 return true;
genesis 1300 }
genesis 1301
genesis 1302 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
genesis 1303 {
genesis 1304 nIndex = -1;
genesis 1305 keypool.vchPubKey.clear();
genesis 1306 CRITICAL_BLOCK(cs_wallet)
genesis 1307 {
genesis 1308 if (!IsLocked())
genesis 1309 TopUpKeyPool();
genesis 1310
genesis 1311 // Get the oldest key
genesis 1312 if(setKeyPool.empty())
genesis 1313 return;
genesis 1314
genesis 1315 CWalletDB walletdb(strWalletFile);
genesis 1316
genesis 1317 nIndex = *(setKeyPool.begin());
genesis 1318 setKeyPool.erase(setKeyPool.begin());
genesis 1319 if (!walletdb.ReadPool(nIndex, keypool))
genesis 1320 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
genesis 1321 if (!HaveKey(Hash160(keypool.vchPubKey)))
genesis 1322 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
genesis 1323 assert(!keypool.vchPubKey.empty());
genesis 1324 printf("keypool reserve %"PRI64d"\n", nIndex);
genesis 1325 }
genesis 1326 }
genesis 1327
genesis 1328 void CWallet::KeepKey(int64 nIndex)
genesis 1329 {
genesis 1330 // Remove from key pool
genesis 1331 if (fFileBacked)
genesis 1332 {
genesis 1333 CWalletDB walletdb(strWalletFile);
genesis 1334 walletdb.ErasePool(nIndex);
genesis 1335 }
genesis 1336 printf("keypool keep %"PRI64d"\n", nIndex);
genesis 1337 }
genesis 1338
genesis 1339 void CWallet::ReturnKey(int64 nIndex)
genesis 1340 {
genesis 1341 // Return to key pool
genesis 1342 CRITICAL_BLOCK(cs_wallet)
genesis 1343 setKeyPool.insert(nIndex);
genesis 1344 printf("keypool return %"PRI64d"\n", nIndex);
genesis 1345 }
genesis 1346
genesis 1347 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
genesis 1348 {
genesis 1349 int64 nIndex = 0;
genesis 1350 CKeyPool keypool;
genesis 1351 CRITICAL_BLOCK(cs_wallet)
genesis 1352 {
genesis 1353 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1354 if (nIndex == -1)
genesis 1355 {
genesis 1356 if (fAllowReuse && !vchDefaultKey.empty())
genesis 1357 {
genesis 1358 result = vchDefaultKey;
genesis 1359 return true;
genesis 1360 }
genesis 1361 if (IsLocked()) return false;
genesis 1362 result = GenerateNewKey();
genesis 1363 return true;
genesis 1364 }
genesis 1365 KeepKey(nIndex);
genesis 1366 result = keypool.vchPubKey;
genesis 1367 }
genesis 1368 return true;
genesis 1369 }
genesis 1370
genesis 1371 int64 CWallet::GetOldestKeyPoolTime()
genesis 1372 {
genesis 1373 int64 nIndex = 0;
genesis 1374 CKeyPool keypool;
genesis 1375 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1376 if (nIndex == -1)
genesis 1377 return GetTime();
genesis 1378 ReturnKey(nIndex);
genesis 1379 return keypool.nTime;
genesis 1380 }
genesis 1381
genesis 1382 vector<unsigned char> CReserveKey::GetReservedKey()
genesis 1383 {
genesis 1384 if (nIndex == -1)
genesis 1385 {
genesis 1386 CKeyPool keypool;
genesis 1387 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1388 if (nIndex != -1)
genesis 1389 vchPubKey = keypool.vchPubKey;
genesis 1390 else
genesis 1391 {
genesis 1392 printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
genesis 1393 vchPubKey = pwallet->vchDefaultKey;
genesis 1394 }
genesis 1395 }
genesis 1396 assert(!vchPubKey.empty());
genesis 1397 return vchPubKey;
genesis 1398 }
genesis 1399
genesis 1400 void CReserveKey::KeepKey()
genesis 1401 {
genesis 1402 if (nIndex != -1)
genesis 1403 pwallet->KeepKey(nIndex);
genesis 1404 nIndex = -1;
genesis 1405 vchPubKey.clear();
genesis 1406 }
genesis 1407
genesis 1408 void CReserveKey::ReturnKey()
genesis 1409 {
genesis 1410 if (nIndex != -1)
genesis 1411 pwallet->ReturnKey(nIndex);
genesis 1412 nIndex = -1;
genesis 1413 vchPubKey.clear();
genesis 1414 }
genesis 1415