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 // If default receiving address gets used, replace it with a new one
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 // Notify UI
genesis 286 vWalletUpdated.push_back(hash);
genesis 287
genesis 288 // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
genesis 289 WalletUpdateSpent(wtx);
genesis 290 }
genesis 291
genesis 292 // Refresh UI
genesis 293 MainFrameRepaint();
genesis 294 return true;
genesis 295 }
genesis 296
genesis 297 // Add a transaction to the wallet, or update it.
genesis 298 // pblock is optional, but should be provided if the transaction is known to be in a block.
genesis 299 // If fUpdate is true, existing transactions will be updated.
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 // Get merkle branch if transaction was found in a block
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 // Returns -1 if it wasn't being tracked
genesis 374 int nRequests = -1;
genesis 375 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 376 {
genesis 377 if (IsCoinBase())
genesis 378 {
genesis 379 // Generated block
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 // Did anyone request this transaction?
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 // How about the block it's in?
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; // If it's in someone else's block it must have got out
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 // Compute fee:
genesis 428 int64 nDebit = GetDebit();
genesis 429 if (nDebit > 0) // debit>0 means we signed/sent this transaction
genesis 430 {
genesis 431 int64 nValueOut = GetValueOut();
genesis 432 nFee = nDebit - nValueOut;
genesis 433 }
genesis 434
genesis 435 // Sent/received. Standard client will never generate a send-to-multiple-recipients,
genesis 436 // but non-standard clients might (so return a list of address/amount pairs)
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 {
genesis 443 printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
genesis 444 this->GetHash().ToString().c_str());
genesis 445 address = " unknown ";
genesis 446 }
genesis 447
genesis 448 // Don't report 'change' txouts
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 // This critsect is OK because txdb is already open
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 {
genesis 540 printf("ERROR: AddSupportingTransactions() : unsupported transaction\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 // Scan the block chain (starting in pindexStart) for transactions
genesis 563 // from or to us. If fUpdate is true, found transactions that already
genesis 564 // exist in the wallet will be updated.
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 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
genesis 606 if (txindex.vSpent.size() != wtx.vout.size())
genesis 607 {
genesis 608 printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
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 {
genesis 624 printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
genesis 625 wtx.MarkDirty();
genesis 626 wtx.WriteToDisk();
genesis 627 }
genesis 628 }
genesis 629 else
genesis 630 {
genesis 631 // Reaccept any txes of ours that aren't already in a block
genesis 632 if (!wtx.IsCoinBase())
genesis 633 wtx.AcceptWalletTransaction(txdb, false);
genesis 634 }
genesis 635 }
genesis 636 if (!vMissingTx.empty())
genesis 637 {
genesis 638 // TODO: optimize this to scan just part of the block chain?
genesis 639 if (ScanForWalletTransactions(pindexGenesisBlock))
genesis 640 fRepeat = true; // Found missing transactions: re-do Reaccept.
genesis 641 }
genesis 642 }
genesis 643 }
genesis 644
genesis 645 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
genesis 646 {
genesis 647 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
genesis 648 {
genesis 649 if (!tx.IsCoinBase())
genesis 650 {
genesis 651 uint256 hash = tx.GetHash();
genesis 652 if (!txdb.ContainsTx(hash))
genesis 653 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
genesis 654 }
genesis 655 }
genesis 656 if (!IsCoinBase())
genesis 657 {
genesis 658 uint256 hash = GetHash();
genesis 659 if (!txdb.ContainsTx(hash))
genesis 660 {
genesis 661 printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
genesis 662 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
genesis 663 }
genesis 664 }
genesis 665 }
genesis 666
genesis 667 void CWalletTx::RelayWalletTransaction()
genesis 668 {
genesis 669 CTxDB txdb("r");
genesis 670 RelayWalletTransaction(txdb);
genesis 671 }
genesis 672
genesis 673 void CWallet::ResendWalletTransactions()
genesis 674 {
genesis 675 // Do this infrequently and randomly to avoid giving away
genesis 676 // that these are our transactions.
genesis 677 static int64 nNextTime;
genesis 678 if (GetTime() < nNextTime)
genesis 679 return;
genesis 680 bool fFirst = (nNextTime == 0);
genesis 681 nNextTime = GetTime() + GetRand(30 * 60);
genesis 682 if (fFirst)
genesis 683 return;
genesis 684
genesis 685 // Only do it if there's been a new block since last time
genesis 686 static int64 nLastTime;
genesis 687 if (nTimeBestReceived < nLastTime)
genesis 688 return;
genesis 689 nLastTime = GetTime();
genesis 690
genesis 691 // Rebroadcast any of our txes that aren't in a block yet
genesis 692 printf("ResendWalletTransactions()\n");
genesis 693 CTxDB txdb("r");
genesis 694 CRITICAL_BLOCK(cs_wallet)
genesis 695 {
genesis 696 // Sort them in chronological order
genesis 697 multimap<unsigned int, CWalletTx*> mapSorted;
genesis 698 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 699 {
genesis 700 CWalletTx& wtx = item.second;
genesis 701 // Don't rebroadcast until it's had plenty of time that
genesis 702 // it should have gotten in already by now.
genesis 703 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
genesis 704 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
genesis 705 }
genesis 706 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
genesis 707 {
genesis 708 CWalletTx& wtx = *item.second;
genesis 709 wtx.RelayWalletTransaction(txdb);
genesis 710 }
genesis 711 }
genesis 712 }
genesis 713
genesis 714
genesis 715
genesis 716
genesis 717
genesis 718
genesis 719 //////////////////////////////////////////////////////////////////////////////
genesis 720 //
genesis 721 // Actions
genesis 722 //
genesis 723
genesis 724
genesis 725 int64 CWallet::GetBalance() const
genesis 726 {
genesis 727 int64 nTotal = 0;
genesis 728 CRITICAL_BLOCK(cs_wallet)
genesis 729 {
genesis 730 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 731 {
genesis 732 const CWalletTx* pcoin = &(*it).second;
genesis 733 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 734 continue;
genesis 735 nTotal += pcoin->GetAvailableCredit();
genesis 736 }
genesis 737 }
genesis 738
genesis 739 return nTotal;
genesis 740 }
genesis 741
genesis 742 int64 CWallet::GetUnconfirmedBalance() const
genesis 743 {
genesis 744 int64 nTotal = 0;
genesis 745 CRITICAL_BLOCK(cs_wallet)
genesis 746 {
genesis 747 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 748 {
genesis 749 const CWalletTx* pcoin = &(*it).second;
genesis 750 if (pcoin->IsFinal() && pcoin->IsConfirmed())
genesis 751 continue;
genesis 752 nTotal += pcoin->GetAvailableCredit();
genesis 753 }
genesis 754 }
genesis 755 return nTotal;
genesis 756 }
genesis 757
genesis 758 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 759 {
genesis 760 setCoinsRet.clear();
genesis 761 nValueRet = 0;
genesis 762
genesis 763 // List of values less than target
genesis 764 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
genesis 765 coinLowestLarger.first = INT64_MAX;
genesis 766 coinLowestLarger.second.first = NULL;
genesis 767 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
genesis 768 int64 nTotalLower = 0;
genesis 769
genesis 770 CRITICAL_BLOCK(cs_wallet)
genesis 771 {
genesis 772 vector<const CWalletTx*> vCoins;
genesis 773 vCoins.reserve(mapWallet.size());
genesis 774 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 775 vCoins.push_back(&(*it).second);
genesis 776 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
genesis 777
genesis 778 BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
genesis 779 {
genesis 780 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 781 continue;
genesis 782
genesis 783 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
genesis 784 continue;
genesis 785
genesis 786 int nDepth = pcoin->GetDepthInMainChain();
genesis 787 if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
genesis 788 continue;
genesis 789
genesis 790 for (int i = 0; i < pcoin->vout.size(); i++)
genesis 791 {
genesis 792 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
genesis 793 continue;
genesis 794
genesis 795 int64 n = pcoin->vout[i].nValue;
genesis 796
genesis 797 if (n <= 0)
genesis 798 continue;
genesis 799
genesis 800 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
genesis 801
genesis 802 if (n == nTargetValue)
genesis 803 {
genesis 804 setCoinsRet.insert(coin.second);
genesis 805 nValueRet += coin.first;
genesis 806 return true;
genesis 807 }
genesis 808 else if (n < nTargetValue + CENT)
genesis 809 {
genesis 810 vValue.push_back(coin);
genesis 811 nTotalLower += n;
genesis 812 }
genesis 813 else if (n < coinLowestLarger.first)
genesis 814 {
genesis 815 coinLowestLarger = coin;
genesis 816 }
genesis 817 }
genesis 818 }
genesis 819 }
genesis 820
genesis 821 if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
genesis 822 {
genesis 823 for (int i = 0; i < vValue.size(); ++i)
genesis 824 {
genesis 825 setCoinsRet.insert(vValue[i].second);
genesis 826 nValueRet += vValue[i].first;
genesis 827 }
genesis 828 return true;
genesis 829 }
genesis 830
genesis 831 if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
genesis 832 {
genesis 833 if (coinLowestLarger.second.first == NULL)
genesis 834 return false;
genesis 835 setCoinsRet.insert(coinLowestLarger.second);
genesis 836 nValueRet += coinLowestLarger.first;
genesis 837 return true;
genesis 838 }
genesis 839
genesis 840 if (nTotalLower >= nTargetValue + CENT)
genesis 841 nTargetValue += CENT;
genesis 842
genesis 843 // Solve subset sum by stochastic approximation
genesis 844 sort(vValue.rbegin(), vValue.rend());
genesis 845 vector<char> vfIncluded;
genesis 846 vector<char> vfBest(vValue.size(), true);
genesis 847 int64 nBest = nTotalLower;
genesis 848
genesis 849 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
genesis 850 {
genesis 851 vfIncluded.assign(vValue.size(), false);
genesis 852 int64 nTotal = 0;
genesis 853 bool fReachedTarget = false;
genesis 854 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
genesis 855 {
genesis 856 for (int i = 0; i < vValue.size(); i++)
genesis 857 {
genesis 858 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
genesis 859 {
genesis 860 nTotal += vValue[i].first;
genesis 861 vfIncluded[i] = true;
genesis 862 if (nTotal >= nTargetValue)
genesis 863 {
genesis 864 fReachedTarget = true;
genesis 865 if (nTotal < nBest)
genesis 866 {
genesis 867 nBest = nTotal;
genesis 868 vfBest = vfIncluded;
genesis 869 }
genesis 870 nTotal -= vValue[i].first;
genesis 871 vfIncluded[i] = false;
genesis 872 }
genesis 873 }
genesis 874 }
genesis 875 }
genesis 876 }
genesis 877
genesis 878 // If the next larger is still closer, return it
genesis 879 if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
genesis 880 {
genesis 881 setCoinsRet.insert(coinLowestLarger.second);
genesis 882 nValueRet += coinLowestLarger.first;
genesis 883 }
genesis 884 else {
genesis 885 for (int i = 0; i < vValue.size(); i++)
genesis 886 if (vfBest[i])
genesis 887 {
genesis 888 setCoinsRet.insert(vValue[i].second);
genesis 889 nValueRet += vValue[i].first;
genesis 890 }
genesis 891
genesis 892 //// debug print
genesis 893 printf("SelectCoins() best subset: ");
genesis 894 for (int i = 0; i < vValue.size(); i++)
genesis 895 if (vfBest[i])
genesis 896 printf("%s ", FormatMoney(vValue[i].first).c_str());
genesis 897 printf("total %s\n", FormatMoney(nBest).c_str());
genesis 898 }
genesis 899
genesis 900 return true;
genesis 901 }
genesis 902
genesis 903 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 904 {
genesis 905 return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
genesis 906 SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
genesis 907 SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
genesis 908 }
genesis 909
genesis 910
genesis 911
genesis 912
genesis 913 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 914 {
genesis 915 int64 nValue = 0;
genesis 916 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 917 {
genesis 918 if (nValue < 0)
genesis 919 return false;
genesis 920 nValue += s.second;
genesis 921 }
genesis 922 if (vecSend.empty() || nValue < 0)
genesis 923 return false;
genesis 924
genesis 925 wtxNew.pwallet = this;
genesis 926
genesis 927 CRITICAL_BLOCK(cs_main)
genesis 928 CRITICAL_BLOCK(cs_wallet)
genesis 929 {
genesis 930 // txdb must be opened before the mapWallet lock
genesis 931 CTxDB txdb("r");
genesis 932 {
genesis 933 nFeeRet = nTransactionFee;
genesis 934 loop
genesis 935 {
genesis 936 wtxNew.vin.clear();
genesis 937 wtxNew.vout.clear();
genesis 938 wtxNew.fFromMe = true;
genesis 939
genesis 940 int64 nTotalValue = nValue + nFeeRet;
genesis 941 double dPriority = 0;
genesis 942 // vouts to the payees
genesis 943 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 944 wtxNew.vout.push_back(CTxOut(s.second, s.first));
genesis 945
genesis 946 // Choose coins to use
genesis 947 set<pair<const CWalletTx*,unsigned int> > setCoins;
genesis 948 int64 nValueIn = 0;
genesis 949 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
genesis 950 return false;
genesis 951 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
genesis 952 {
genesis 953 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
genesis 954 dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
genesis 955 }
genesis 956
genesis 957 int64 nChange = nValueIn - nValue - nFeeRet;
genesis 958 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
genesis 959 // or until nChange becomes zero
genesis 960 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
genesis 961 {
genesis 962 int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
genesis 963 nChange -= nMoveToFee;
genesis 964 nFeeRet += nMoveToFee;
genesis 965 }
genesis 966
genesis 967 if (nChange > 0)
genesis 968 {
genesis 969 // Note: We use a new key here to keep it from being obvious which side is the change.
genesis 970 // The drawback is that by not reusing a previous key, the change may be lost if a
genesis 971 // backup is restored, if the backup doesn't have the new private key for the change.
genesis 972 // If we reused the old key, it would be possible to add code to look for and
genesis 973 // rediscover unknown transactions that were written with keys of ours to recover
genesis 974 // post-backup change.
genesis 975
genesis 976 // Reserve a new key pair from key pool
genesis 977 vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
genesis 978 // assert(mapKeys.count(vchPubKey));
genesis 979
genesis 980 // Fill a vout to ourself, using same address type as the payment
genesis 981 CScript scriptChange;
genesis 982 if (vecSend[0].first.GetBitcoinAddress().IsValid())
genesis 983 scriptChange.SetBitcoinAddress(vchPubKey);
genesis 984 else
genesis 985 scriptChange << vchPubKey << OP_CHECKSIG;
genesis 986
genesis 987 // Insert change txn at random position:
genesis 988 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
genesis 989 wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
genesis 990 }
genesis 991 else
genesis 992 reservekey.ReturnKey();
genesis 993
genesis 994 // Fill vin
genesis 995 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 996 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
genesis 997
genesis 998 // Sign
genesis 999 int nIn = 0;
genesis 1000 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 1001 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
genesis 1002 return false;
genesis 1003
genesis 1004 // Limit size
genesis 1005 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
genesis 1006 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
genesis 1007 return false;
genesis 1008 dPriority /= nBytes;
genesis 1009
genesis 1010 // Check that enough fee is included
genesis 1011 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
genesis 1012 bool fAllowFree = CTransaction::AllowFree(dPriority);
genesis 1013 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
genesis 1014 if (nFeeRet < max(nPayFee, nMinFee))
genesis 1015 {
genesis 1016 nFeeRet = max(nPayFee, nMinFee);
genesis 1017 continue;
genesis 1018 }
genesis 1019
genesis 1020 // Fill vtxPrev by copying from previous transactions vtxPrev
genesis 1021 wtxNew.AddSupportingTransactions(txdb);
genesis 1022 wtxNew.fTimeReceivedIsTxTime = true;
genesis 1023
genesis 1024 break;
genesis 1025 }
genesis 1026 }
genesis 1027 }
genesis 1028 return true;
genesis 1029 }
genesis 1030
genesis 1031 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 1032 {
genesis 1033 vector< pair<CScript, int64> > vecSend;
genesis 1034 vecSend.push_back(make_pair(scriptPubKey, nValue));
genesis 1035 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
genesis 1036 }
genesis 1037
genesis 1038 // Call after CreateTransaction unless you want to abort
genesis 1039 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
genesis 1040 {
genesis 1041 CRITICAL_BLOCK(cs_main)
genesis 1042 CRITICAL_BLOCK(cs_wallet)
genesis 1043 {
genesis 1044 printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
genesis 1045 {
genesis 1046 // This is only to keep the database open to defeat the auto-flush for the
genesis 1047 // duration of this scope. This is the only place where this optimization
genesis 1048 // maybe makes sense; please don't do it anywhere else.
genesis 1049 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
genesis 1050
genesis 1051 // Take key pair from key pool so it won't be used again
genesis 1052 reservekey.KeepKey();
genesis 1053
genesis 1054 // Add tx to wallet, because if it has change it's also ours,
genesis 1055 // otherwise just for transaction history.
genesis 1056 AddToWallet(wtxNew);
genesis 1057
genesis 1058 // Mark old coins as spent
genesis 1059 set<CWalletTx*> setCoins;
genesis 1060 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
genesis 1061 {
genesis 1062 CWalletTx &coin = mapWallet[txin.prevout.hash];
genesis 1063 coin.pwallet = this;
genesis 1064 coin.MarkSpent(txin.prevout.n);
genesis 1065 coin.WriteToDisk();
genesis 1066 vWalletUpdated.push_back(coin.GetHash());
genesis 1067 }
genesis 1068
genesis 1069 if (fFileBacked)
genesis 1070 delete pwalletdb;
genesis 1071 }
genesis 1072
genesis 1073 // Track how many getdata requests our transaction gets
genesis 1074 mapRequestCount[wtxNew.GetHash()] = 0;
genesis 1075
genesis 1076 // Broadcast
genesis 1077 if (!wtxNew.AcceptToMemoryPool())
genesis 1078 {
genesis 1079 // This must not fail. The transaction has already been signed and recorded.
genesis 1080 printf("CommitTransaction() : Error: Transaction not valid");
genesis 1081 return false;
genesis 1082 }
genesis 1083 wtxNew.RelayWalletTransaction();
genesis 1084 }
genesis 1085 MainFrameRepaint();
genesis 1086 return true;
genesis 1087 }
genesis 1088
genesis 1089
genesis 1090
genesis 1091
genesis 1092 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1093 {
genesis 1094 CReserveKey reservekey(this);
genesis 1095 int64 nFeeRequired;
genesis 1096
genesis 1097 if (IsLocked())
genesis 1098 {
genesis 1099 string strError = _("Error: Wallet locked, unable to create transaction ");
genesis 1100 printf("SendMoney() : %s", strError.c_str());
genesis 1101 return strError;
genesis 1102 }
genesis 1103 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
genesis 1104 {
genesis 1105 string strError;
genesis 1106 if (nValue + nFeeRequired > GetBalance())
genesis 1107 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 1108 else
genesis 1109 strError = _("Error: Transaction creation failed ");
genesis 1110 printf("SendMoney() : %s", strError.c_str());
genesis 1111 return strError;
genesis 1112 }
genesis 1113
genesis 1114 if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
genesis 1115 return "ABORTED";
genesis 1116
genesis 1117 if (!CommitTransaction(wtxNew, reservekey))
genesis 1118 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 1119
genesis 1120 MainFrameRepaint();
genesis 1121 return "";
genesis 1122 }
genesis 1123
genesis 1124
genesis 1125
genesis 1126 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1127 {
genesis 1128 // Check amount
genesis 1129 if (nValue <= 0)
genesis 1130 return _("Invalid amount");
genesis 1131 if (nValue + nTransactionFee > GetBalance())
genesis 1132 return _("Insufficient funds");
genesis 1133
genesis 1134 // Parse bitcoin address
genesis 1135 CScript scriptPubKey;
genesis 1136 scriptPubKey.SetBitcoinAddress(address);
genesis 1137
genesis 1138 return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
genesis 1139 }
genesis 1140
genesis 1141
genesis 1142
genesis 1143
genesis 1144 int CWallet::LoadWallet(bool& fFirstRunRet)
genesis 1145 {
genesis 1146 if (!fFileBacked)
genesis 1147 return false;
genesis 1148 fFirstRunRet = false;
genesis 1149 int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
genesis 1150 if (nLoadWalletRet == DB_NEED_REWRITE)
genesis 1151 {
genesis 1152 if (CDB::Rewrite(strWalletFile, "\x04pool"))
genesis 1153 {
genesis 1154 setKeyPool.clear();
genesis 1155 // Note: can't top-up keypool here, because wallet is locked.
genesis 1156 // User will be prompted to unlock wallet the next operation
genesis 1157 // the requires a new key.
genesis 1158 }
genesis 1159 nLoadWalletRet = DB_NEED_REWRITE;
genesis 1160 }
genesis 1161
genesis 1162 if (nLoadWalletRet != DB_LOAD_OK)
genesis 1163 return nLoadWalletRet;
genesis 1164 fFirstRunRet = vchDefaultKey.empty();
genesis 1165
genesis 1166 if (!HaveKey(Hash160(vchDefaultKey)))
genesis 1167 {
genesis 1168 // Create new keyUser and set as default key
genesis 1169 RandAddSeedPerfmon();
genesis 1170
genesis 1171 std::vector<unsigned char> newDefaultKey;
genesis 1172 if (!GetKeyFromPool(newDefaultKey, false))
genesis 1173 return DB_LOAD_FAIL;
genesis 1174 SetDefaultKey(newDefaultKey);
genesis 1175 if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
genesis 1176 return DB_LOAD_FAIL;
genesis 1177 }
genesis 1178
genesis 1179 CreateThread(ThreadFlushWalletDB, &strWalletFile);
genesis 1180 return DB_LOAD_OK;
genesis 1181 }
genesis 1182
genesis 1183
genesis 1184 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
genesis 1185 {
genesis 1186 mapAddressBook[address] = strName;
genesis 1187 if (!fFileBacked)
genesis 1188 return false;
genesis 1189 return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
genesis 1190 }
genesis 1191
genesis 1192 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
genesis 1193 {
genesis 1194 mapAddressBook.erase(address);
genesis 1195 if (!fFileBacked)
genesis 1196 return false;
genesis 1197 return CWalletDB(strWalletFile).EraseName(address.ToString());
genesis 1198 }
genesis 1199
genesis 1200
genesis 1201 void CWallet::PrintWallet(const CBlock& block)
genesis 1202 {
genesis 1203 CRITICAL_BLOCK(cs_wallet)
genesis 1204 {
genesis 1205 if (mapWallet.count(block.vtx[0].GetHash()))
genesis 1206 {
genesis 1207 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
genesis 1208 printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
genesis 1209 }
genesis 1210 }
genesis 1211 printf("\n");
genesis 1212 }
genesis 1213
genesis 1214 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
genesis 1215 {
genesis 1216 CRITICAL_BLOCK(cs_wallet)
genesis 1217 {
genesis 1218 map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
genesis 1219 if (mi != mapWallet.end())
genesis 1220 {
genesis 1221 wtx = (*mi).second;
genesis 1222 return true;
genesis 1223 }
genesis 1224 }
genesis 1225 return false;
genesis 1226 }
genesis 1227
genesis 1228 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
genesis 1229 {
genesis 1230 if (fFileBacked)
genesis 1231 {
genesis 1232 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
genesis 1233 return false;
genesis 1234 }
genesis 1235 vchDefaultKey = vchPubKey;
genesis 1236 return true;
genesis 1237 }
genesis 1238
genesis 1239 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
genesis 1240 {
genesis 1241 if (!pwallet->fFileBacked)
genesis 1242 return false;
genesis 1243 strWalletFileOut = pwallet->strWalletFile;
genesis 1244 return true;
genesis 1245 }
genesis 1246
genesis 1247 //
genesis 1248 // Mark old keypool keys as used,
genesis 1249 // and generate all new keys
genesis 1250 //
genesis 1251 bool CWallet::NewKeyPool()
genesis 1252 {
genesis 1253 CRITICAL_BLOCK(cs_wallet)
genesis 1254 {
genesis 1255 CWalletDB walletdb(strWalletFile);
genesis 1256 BOOST_FOREACH(int64 nIndex, setKeyPool)
genesis 1257 walletdb.ErasePool(nIndex);
genesis 1258 setKeyPool.clear();
genesis 1259
genesis 1260 if (IsLocked())
genesis 1261 return false;
genesis 1262
genesis 1263 int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
genesis 1264 for (int i = 0; i < nKeys; i++)
genesis 1265 {
genesis 1266 int64 nIndex = i+1;
genesis 1267 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
genesis 1268 setKeyPool.insert(nIndex);
genesis 1269 }
genesis 1270 printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
genesis 1271 }
genesis 1272 return true;
genesis 1273 }
genesis 1274
genesis 1275 bool CWallet::TopUpKeyPool()
genesis 1276 {
genesis 1277 CRITICAL_BLOCK(cs_wallet)
genesis 1278 {
genesis 1279 if (IsLocked())
genesis 1280 return false;
genesis 1281
genesis 1282 CWalletDB walletdb(strWalletFile);
genesis 1283
genesis 1284 // Top up key pool
genesis 1285 int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
genesis 1286 while (setKeyPool.size() < nTargetSize+1)
genesis 1287 {
genesis 1288 int64 nEnd = 1;
genesis 1289 if (!setKeyPool.empty())
genesis 1290 nEnd = *(--setKeyPool.end()) + 1;
genesis 1291 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
genesis 1292 throw runtime_error("TopUpKeyPool() : writing generated key failed");
genesis 1293 setKeyPool.insert(nEnd);
genesis 1294 printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
genesis 1295 }
genesis 1296 }
genesis 1297 return true;
genesis 1298 }
genesis 1299
genesis 1300 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
genesis 1301 {
genesis 1302 nIndex = -1;
genesis 1303 keypool.vchPubKey.clear();
genesis 1304 CRITICAL_BLOCK(cs_wallet)
genesis 1305 {
genesis 1306 if (!IsLocked())
genesis 1307 TopUpKeyPool();
genesis 1308
genesis 1309 // Get the oldest key
genesis 1310 if(setKeyPool.empty())
genesis 1311 return;
genesis 1312
genesis 1313 CWalletDB walletdb(strWalletFile);
genesis 1314
genesis 1315 nIndex = *(setKeyPool.begin());
genesis 1316 setKeyPool.erase(setKeyPool.begin());
genesis 1317 if (!walletdb.ReadPool(nIndex, keypool))
genesis 1318 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
genesis 1319 if (!HaveKey(Hash160(keypool.vchPubKey)))
genesis 1320 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
genesis 1321 assert(!keypool.vchPubKey.empty());
genesis 1322 printf("keypool reserve %"PRI64d"\n", nIndex);
genesis 1323 }
genesis 1324 }
genesis 1325
genesis 1326 void CWallet::KeepKey(int64 nIndex)
genesis 1327 {
genesis 1328 // Remove from key pool
genesis 1329 if (fFileBacked)
genesis 1330 {
genesis 1331 CWalletDB walletdb(strWalletFile);
genesis 1332 walletdb.ErasePool(nIndex);
genesis 1333 }
genesis 1334 printf("keypool keep %"PRI64d"\n", nIndex);
genesis 1335 }
genesis 1336
genesis 1337 void CWallet::ReturnKey(int64 nIndex)
genesis 1338 {
genesis 1339 // Return to key pool
genesis 1340 CRITICAL_BLOCK(cs_wallet)
genesis 1341 setKeyPool.insert(nIndex);
genesis 1342 printf("keypool return %"PRI64d"\n", nIndex);
genesis 1343 }
genesis 1344
genesis 1345 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
genesis 1346 {
genesis 1347 int64 nIndex = 0;
genesis 1348 CKeyPool keypool;
genesis 1349 CRITICAL_BLOCK(cs_wallet)
genesis 1350 {
genesis 1351 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1352 if (nIndex == -1)
genesis 1353 {
genesis 1354 if (fAllowReuse && !vchDefaultKey.empty())
genesis 1355 {
genesis 1356 result = vchDefaultKey;
genesis 1357 return true;
genesis 1358 }
genesis 1359 if (IsLocked()) return false;
genesis 1360 result = GenerateNewKey();
genesis 1361 return true;
genesis 1362 }
genesis 1363 KeepKey(nIndex);
genesis 1364 result = keypool.vchPubKey;
genesis 1365 }
genesis 1366 return true;
genesis 1367 }
genesis 1368
genesis 1369 int64 CWallet::GetOldestKeyPoolTime()
genesis 1370 {
genesis 1371 int64 nIndex = 0;
genesis 1372 CKeyPool keypool;
genesis 1373 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1374 if (nIndex == -1)
genesis 1375 return GetTime();
genesis 1376 ReturnKey(nIndex);
genesis 1377 return keypool.nTime;
genesis 1378 }
genesis 1379
genesis 1380 vector<unsigned char> CReserveKey::GetReservedKey()
genesis 1381 {
genesis 1382 if (nIndex == -1)
genesis 1383 {
genesis 1384 CKeyPool keypool;
genesis 1385 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1386 if (nIndex != -1)
genesis 1387 vchPubKey = keypool.vchPubKey;
genesis 1388 else
genesis 1389 {
genesis 1390 printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
genesis 1391 vchPubKey = pwallet->vchDefaultKey;
genesis 1392 }
genesis 1393 }
genesis 1394 assert(!vchPubKey.empty());
genesis 1395 return vchPubKey;
genesis 1396 }
genesis 1397
genesis 1398 void CReserveKey::KeepKey()
genesis 1399 {
genesis 1400 if (nIndex != -1)
genesis 1401 pwallet->KeepKey(nIndex);
genesis 1402 nIndex = -1;
genesis 1403 vchPubKey.clear();
genesis 1404 }
genesis 1405
genesis 1406 void CReserveKey::ReturnKey()
genesis 1407 {
genesis 1408 if (nIndex != -1)
genesis 1409 pwallet->ReturnKey(nIndex);
genesis 1410 nIndex = -1;
genesis 1411 vchPubKey.clear();
genesis 1412 }
genesis 1413